1
0
forked from finn/tinyboard
Files
tinyboard/hub/setup-hub.sh

265 lines
8.5 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${GREEN}[+]${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
die() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
header() { echo -e "\n${CYAN}══════════════════════════════════════════${NC}"; echo -e "${CYAN} $*${NC}"; echo -e "${CYAN}══════════════════════════════════════════${NC}"; }
check_deps() {
local missing=()
for cmd in "$@"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing+=("$cmd")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
die "Missing required dependencies: ${missing[*]}"
fi
}
check_permissions() {
local file="$1"
local label="$2"
if [ ! -f "$file" ]; then
warn "Permission check: $label not found at $file"
return
fi
local perms
perms=$(stat -c "%a" "$file" 2>/dev/null || stat -f "%OLp" "$file" 2>/dev/null)
if [ -z "$perms" ]; then
warn "Could not read permissions for $label ($file)"
return
fi
local world="${perms: -1}"
local group="${perms: -2:1}"
if [ "$world" != "0" ] || [ "$group" != "0" ]; then
warn "UNSAFE PERMISSIONS on $label ($file): $perms — should be 600 or 400"
warn "Fixing permissions automatically..."
chmod 600 "$file"
info "Permissions fixed: $file is now 600"
else
info "Permissions OK: $label ($file) = $perms"
fi
}
[ "$(id -u)" -eq 0 ] || die "Run as root"
check_deps ssh ssh-keygen systemctl useradd groupadd
header "TinyBoard Hub Setup"
read -rp "Hub username [armbian]: " HUB_USER
HUB_USER="${HUB_USER:-armbian}"
header "Detecting Package Manager"
if command -v apt-get >/dev/null 2>&1; then
PKG_MANAGER="apt"
PKG_INSTALL="apt-get install -y -q"
OPENSSH_PKG="openssh-server"
FUSE_PKG="fuse"
info "Detected: apt (Debian/Ubuntu)"
apt-get update -q
elif command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
PKG_INSTALL="dnf install -y -q"
OPENSSH_PKG="openssh-server"
FUSE_PKG="fuse"
info "Detected: dnf (Fedora/RHEL/Alma/Rocky)"
dnf check-update -q || true
elif command -v yum >/dev/null 2>&1; then
PKG_MANAGER="yum"
PKG_INSTALL="yum install -y -q"
OPENSSH_PKG="openssh-server"
FUSE_PKG="fuse"
info "Detected: yum (older RHEL/CentOS)"
yum check-update -q || true
elif command -v pacman >/dev/null 2>&1; then
PKG_MANAGER="pacman"
PKG_INSTALL="pacman -S --noconfirm --quiet"
OPENSSH_PKG="openssh"
FUSE_PKG="fuse3"
info "Detected: pacman (Arch)"
pacman -Sy --quiet
else
die "No supported package manager found (apt, dnf, yum, pacman)"
fi
header "Installing Packages"
info "Installing curl if missing..."
if ! command -v curl >/dev/null 2>&1; then
$PKG_INSTALL curl
fi
$PKG_INSTALL "$OPENSSH_PKG" "$FUSE_PKG" git
if ! command -v rclone >/dev/null 2>&1; then
info "Installing rclone..."
if [ "$PKG_MANAGER" = "pacman" ]; then
$PKG_INSTALL rclone
else
curl -fsSL https://rclone.org/install.sh | bash
fi
else
warn "rclone already installed, skipping."
fi
header "Armbian User Setup"
if id "$HUB_USER" >/dev/null 2>&1; then
warn "User '$HUB_USER' already exists, skipping creation."
else
info "Creating $HUB_USER user..."
groupadd -g 1000 "$HUB_USER" 2>/dev/null || true
useradd -m -u 1000 -g 1000 -s /bin/bash "$HUB_USER"
ADDED_TO_GROUP=false
if getent group sudo >/dev/null 2>&1; then
if usermod -aG sudo "$HUB_USER" 2>/dev/null; then
ADDED_TO_GROUP=true
fi
fi
if [ "$ADDED_TO_GROUP" = false ] && getent group wheel >/dev/null 2>&1; then
if usermod -aG wheel "$HUB_USER" 2>/dev/null; then
ADDED_TO_GROUP=true
fi
fi
if [ "$ADDED_TO_GROUP" = false ]; then
warn "Neither sudo nor wheel group found — $HUB_USER user has no sudo access."
fi
info "$HUB_USER user created."
echo ""
warn "Set a password for the $HUB_USER user:"
passwd "$HUB_USER"
fi
ARMBIAN_HOME="/home/$HUB_USER"
SSH_DIR="$ARMBIAN_HOME/.ssh"
mkdir -p "$SSH_DIR"
touch "$SSH_DIR/authorized_keys"
chown -R "$HUB_USER":"$HUB_USER" "$SSH_DIR"
chmod 700 "$SSH_DIR"
chmod 600 "$SSH_DIR/authorized_keys"
header "SSH Server Configuration"
SSHD_CONF="/etc/ssh/sshd_config"
[ -f "$SSHD_CONF" ] || die "sshd_config not found at $SSHD_CONF"
for DIRECTIVE in "GatewayPorts yes" "AllowTcpForwarding yes"; do
KEY="${DIRECTIVE%% *}"
if grep -q "^$KEY" "$SSHD_CONF"; then
sed -i "s/^$KEY.*/$DIRECTIVE/" "$SSHD_CONF"
else
echo "$DIRECTIVE" >> "$SSHD_CONF"
fi
info "$DIRECTIVE set."
done
if systemctl enable ssh 2>/dev/null; then
systemctl restart ssh
elif systemctl enable sshd 2>/dev/null; then
systemctl restart sshd
else
warn "Could not enable/restart SSH service — please start it manually."
fi
info "SSH server restarted."
header "Password Authentication"
read -rp "Disable password auth for $HUB_USER and use keys only? [Y/n]: " DISABLE_PASS
DISABLE_PASS="${DISABLE_PASS:-y}"
if [[ "${DISABLE_PASS,,}" == "y" ]]; then
if [ ! -s "$SSH_DIR/authorized_keys" ]; then
warn "No keys found in $SSH_DIR/authorized_keys — skipping password auth disable to avoid lockout."
else
if grep -q "^PasswordAuthentication" "$SSHD_CONF"; then
sed -i "s/^PasswordAuthentication.*/PasswordAuthentication no/" "$SSHD_CONF"
else
echo "PasswordAuthentication no" >> "$SSHD_CONF"
fi
if grep -q "^PubkeyAuthentication" "$SSHD_CONF"; then
sed -i "s/^PubkeyAuthentication.*/PubkeyAuthentication yes/" "$SSHD_CONF"
else
echo "PubkeyAuthentication yes" >> "$SSHD_CONF"
fi
info "Password authentication disabled for $HUB_USER."
echo ""
warn "Restarting SSH will apply the new settings."
warn "If you are connected via SSH, your session may drop."
warn "Make sure you can reconnect using your key before continuing."
read -rp "Press ENTER to restart SSH or CTRL+C to abort..."
if systemctl restart ssh 2>/dev/null; then
info "SSH restarted."
elif systemctl restart sshd 2>/dev/null; then
info "SSH restarted."
else
warn "Could not restart SSH — please restart it manually."
fi
fi
else
info "Password authentication left enabled."
fi
header "FUSE Configuration"
FUSE_CONF="/etc/fuse.conf"
if [ -f "$FUSE_CONF" ]; then
if grep -q "^#user_allow_other" "$FUSE_CONF"; then
sed -i 's/^#user_allow_other/user_allow_other/' "$FUSE_CONF"
info "user_allow_other enabled in $FUSE_CONF."
elif grep -q "^user_allow_other" "$FUSE_CONF"; then
warn "user_allow_other already enabled."
else
echo "user_allow_other" >> "$FUSE_CONF"
info "user_allow_other added to $FUSE_CONF."
fi
else
echo "user_allow_other" > "$FUSE_CONF"
info "$FUSE_CONF created with user_allow_other."
fi
groupadd fuse 2>/dev/null || true
usermod -aG fuse "$HUB_USER" 2>/dev/null || true
info "$HUB_USER added to fuse group."
header "Rclone Setup"
RCLONE_CONF="$ARMBIAN_HOME/.config/rclone/rclone.conf"
mkdir -p "$(dirname "$RCLONE_CONF")"
chown -R "$HUB_USER":"$HUB_USER" "$ARMBIAN_HOME/.config"
if [ ! -f "$RCLONE_CONF" ]; then
touch "$RCLONE_CONF"
chown "$HUB_USER":"$HUB_USER" "$RCLONE_CONF"
info "Empty rclone.conf created at $RCLONE_CONF."
else
warn "rclone.conf already exists, skipping."
fi
header "Permission Checks"
info "Checking SSH directory permissions..."
check_permissions "$SSH_DIR/authorized_keys" "authorized_keys"
check_permissions "$RCLONE_CONF" "rclone.conf"
header "Mount Point Setup"
read -rp "Mount point for spoke filesystems [/mnt/hub]: " MOUNT_POINT
MOUNT_POINT="${MOUNT_POINT:-/mnt/hub}"
mkdir -p "$MOUNT_POINT"
chown "$HUB_USER":"$HUB_USER" "$MOUNT_POINT"
info "Mount point created at $MOUNT_POINT."
header "Hub Setup Complete"
echo -e " Hub user: ${GREEN}$HUB_USER${NC}"
echo -e " SSH config: ${GREEN}GatewayPorts yes, AllowTcpForwarding yes${NC}"
echo -e " FUSE: ${GREEN}user_allow_other enabled${NC}"
echo -e " rclone config: ${GREEN}$RCLONE_CONF${NC}"
echo -e " Mount point: ${GREEN}$MOUNT_POINT${NC}"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo " For each spoke that connects, run:"
echo " ./setup.sh (choose option 2)"
echo ""