diff --git a/hub/setup-hub.sh b/hub/setup-hub.sh new file mode 100644 index 0000000..5afb44e --- /dev/null +++ b/hub/setup-hub.sh @@ -0,0 +1,191 @@ +#!/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}"; } + +[ "$(id -u)" -eq 0 ] || die "Run as root" + +header "TinyBoard Hub Setup" + +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 armbian >/dev/null 2>&1; then + warn "User 'armbian' already exists, skipping creation." +else + info "Creating armbian user..." + groupadd -g 1000 armbian 2>/dev/null || true + useradd -m -u 1000 -g 1000 -s /bin/bash armbian + + ADDED_TO_GROUP=false + if getent group sudo >/dev/null 2>&1; then + usermod -aG sudo armbian && ADDED_TO_GROUP=true + fi + if [ "$ADDED_TO_GROUP" = false ] && getent group wheel >/dev/null 2>&1; then + usermod -aG wheel armbian && ADDED_TO_GROUP=true + fi + if [ "$ADDED_TO_GROUP" = false ]; then + warn "Neither sudo nor wheel group found — armbian user has no sudo access." + fi + + info "armbian user created." + echo "" + warn "Set a password for the armbian user:" + passwd armbian +fi + +ARMBIAN_HOME="/home/armbian" +SSH_DIR="$ARMBIAN_HOME/.ssh" +mkdir -p "$SSH_DIR" +touch "$SSH_DIR/authorized_keys" +chown -R armbian:armbian "$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 "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 armbian 2>/dev/null || true +info "armbian added to fuse group." + +header "Rclone Setup" +RCLONE_CONF="$ARMBIAN_HOME/.config/rclone/rclone.conf" +mkdir -p "$(dirname "$RCLONE_CONF")" +chown -R armbian:armbian "$ARMBIAN_HOME/.config" + +if [ ! -f "$RCLONE_CONF" ]; then + touch "$RCLONE_CONF" + chown armbian:armbian "$RCLONE_CONF" + info "Empty rclone.conf created at $RCLONE_CONF." +else + warn "rclone.conf already exists, skipping." +fi + +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 armbian:armbian "$MOUNT_POINT" +info "Mount point created at $MOUNT_POINT." + +header "Crontab Setup" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HELPER="$SCRIPT_DIR/../hubspoke-helper.sh" +CRON_LINE="@reboot $HELPER hub start-background" +EXISTING=$(crontab -u armbian -l 2>/dev/null || true) + +if echo "$EXISTING" | grep -qF "hub start-background"; then + warn "Crontab entry already exists, skipping." +else + (echo "$EXISTING"; echo "$CRON_LINE") | crontab -u armbian - + info "Added @reboot crontab entry for rclone mount." +fi + +header "Hub Setup Complete" +echo -e " Armbian user: ${GREEN}armbian${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 ""