Files
SSH-Manager/install.sh
T
Yasin DemirandClaude Opus 5 a0476a7e9c Keep sshd_config.d drop-ins working and resolve sftp-server per distro
The wholesale sshd_config replacement is intentional, but two side effects
were not:

- The template had no Include line, so reinstalling dropped the
  `Include /etc/ssh/sshd_config.d/*.conf` that update_ssh_banners_config
  appends, leaving the per-user banner drop-in on disk but inert. Add it as
  the last line: OpenSSH uses the first value it obtains for a keyword, so
  the template's own settings still take precedence over any drop-in and
  only the Match blocks become effective.
- The template hardcoded the Debian path for sftp-server. sshd -t does not
  verify that the binary exists, so SFTP broke silently on distributions
  that ship it elsewhere. install.sh now probes the common locations and
  rewrites the Subsystem line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 06:23:10 +03:00

172 lines
5.6 KiB
Bash

#!/bin/bash
set -e
# Must be root
if [[ $EUID -ne 0 ]]; then
echo "Error: This script must be run as root."
exit 1
fi
echo "Installing TNS243-GLOBAL Manager (localized bundle)..."
# Repo URI used when this script is executed piped (curl | bash) instead of from a local clone
REPO_URL="https://git.yasindemir.link/yasin/SSH-Manager.git"
# Resolve the directory this script lives in (the cloned repo root).
# Supports both:
# git clone $REPO_URL && cd SSH-Manager && bash install.sh
# bash <(curl -sL https://git.yasindemir.link/yasin/SSH-Manager/raw/branch/main/install.sh)
SCRIPT_DIR=""
PIPED_CLONE_DIR=""
if [[ -n "${BASH_SOURCE[0]}" && -f "${BASH_SOURCE[0]}" ]]; then
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
fi
if [[ -z "$SCRIPT_DIR" ]]; then
echo "Piped execution detected - fetching bundle via git..."
if ! command -v git &>/dev/null; then
echo "Error: git is required when running this script piped (curl | bash)."
echo " Install git, or clone the repository manually and run: bash install.sh"
exit 1
fi
PIPED_CLONE_DIR=$(mktemp -d)
git clone -q --depth 1 "$REPO_URL" "$PIPED_CLONE_DIR/SSH-Manager"
SCRIPT_DIR="$PIPED_CLONE_DIR/SSH-Manager"
fi
BUNDLE_INSTALL_DIR="/opt/firewallfalcon-bundle"
# Verify required bundle files exist locally
for required in \
"$SCRIPT_DIR/menu.sh" \
"$SCRIPT_DIR/ssh" \
"$SCRIPT_DIR/panel/panel.py" \
"$SCRIPT_DIR/panel/index.html" \
"$SCRIPT_DIR/udp/udp-custom-linux-amd64" \
"$SCRIPT_DIR/udp/udp-custom-linux-arm" \
"$SCRIPT_DIR/release/falconproxy" \
"$SCRIPT_DIR/release/falconproxyarm" \
"$SCRIPT_DIR/udp/udpgw"
do
if [[ ! -f "$required" ]]; then
echo "Error: Missing bundle file: $required"
exit 1
fi
done
# Stage the bundle on the server so the menu never needs to fetch from GitHub
rm -rf "$BUNDLE_INSTALL_DIR"
mkdir -p "$BUNDLE_INSTALL_DIR"
cp -r "$SCRIPT_DIR/panel" "$BUNDLE_INSTALL_DIR/panel"
cp -r "$SCRIPT_DIR/udp" "$BUNDLE_INSTALL_DIR/udp"
cp -r "$SCRIPT_DIR/release" "$BUNDLE_INSTALL_DIR/release"
# Drop UPX packed originals from the bundle (unpacked binaries are used)
rm -f "$BUNDLE_INSTALL_DIR"/udp/*.upxbackup
# Verify the staged bundle: the menu has no remote fallback, so a missing file
# here would surface later as a failed module install.
for staged in \
"$BUNDLE_INSTALL_DIR/panel/panel.py" \
"$BUNDLE_INSTALL_DIR/panel/index.html" \
"$BUNDLE_INSTALL_DIR/udp/udp-custom-linux-amd64" \
"$BUNDLE_INSTALL_DIR/udp/udp-custom-linux-arm" \
"$BUNDLE_INSTALL_DIR/udp/udpgw" \
"$BUNDLE_INSTALL_DIR/release/falconproxy" \
"$BUNDLE_INSTALL_DIR/release/falconproxyarm"
do
if [[ ! -s "$staged" ]]; then
echo "Error: Bundle staging failed, missing or empty: $staged"
exit 1
fi
done
chmod +x "$BUNDLE_INSTALL_DIR"/udp/udp-custom-linux-* "$BUNDLE_INSTALL_DIR"/udp/udpgw* \
"$BUNDLE_INSTALL_DIR"/release/falconproxy* 2>/dev/null || true
# Install menu from the local copy
cp "$SCRIPT_DIR/menu.sh" /usr/local/bin/menu
chmod +x /usr/local/bin/menu
# Point the menu at the staged bundle (replaces the offline bundle path)
sed -i "s|^FF_BUNDLE_DIR=.*|FF_BUNDLE_DIR=\"$BUNDLE_INSTALL_DIR\"|" /usr/local/bin/menu
echo "Applying TNS243-GLOBAL SSH configuration..."
SSHD_CONFIG="/etc/ssh/sshd_config"
BACKUP="/etc/ssh/sshd_config.backup.$(date +%F-%H%M%S)"
# Backup current SSH config
cp "$SSHD_CONFIG" "$BACKUP"
# Apply TNS243-GLOBAL SSH config from the local copy
cp "$SCRIPT_DIR/ssh" "$SSHD_CONFIG"
chmod 600 "$SSHD_CONFIG"
# The template carries the Debian path for sftp-server. sshd -t does not check
# that the binary exists, so on other distributions SFTP would silently break.
SFTP_SERVER=""
for candidate in \
/usr/lib/openssh/sftp-server \
/usr/libexec/openssh/sftp-server \
/usr/lib/ssh/sftp-server \
/usr/libexec/sftp-server
do
if [[ -x "$candidate" ]]; then
SFTP_SERVER="$candidate"
break
fi
done
if [[ -n "$SFTP_SERVER" ]]; then
sed -i "s|^Subsystem sftp .*|Subsystem sftp $SFTP_SERVER|" "$SSHD_CONFIG"
echo "Using sftp-server: $SFTP_SERVER"
else
echo "WARNING: no sftp-server binary found; leaving the Subsystem line unchanged."
fi
# Validate SSH config (silent)
if ! sshd -t 2>/dev/null; then
echo "ERROR: SSH configuration is invalid!"
echo "Restoring previous configuration..."
cp "$BACKUP" "$SSHD_CONFIG"
exit 1
fi
echo "SSH configuration validated."
# Restart SSH quietly and safely
restart_ssh() {
if command -v systemctl >/dev/null 2>&1; then
systemctl restart sshd 2>/dev/null \
|| systemctl restart ssh 2>/dev/null \
|| return 1
elif command -v service >/dev/null 2>&1; then
service sshd restart 2>/dev/null \
|| service ssh restart 2>/dev/null \
|| return 1
elif command -v rc-service >/dev/null 2>&1; then
rc-service sshd restart 2>/dev/null \
|| rc-service ssh restart 2>/dev/null \
|| return 1
elif [ -x /etc/init.d/sshd ]; then
/etc/init.d/sshd restart >/dev/null 2>&1
elif [ -x /etc/init.d/ssh ]; then
/etc/init.d/ssh restart >/dev/null 2>&1
else
return 1
fi
}
if restart_ssh; then
echo "SSH service restarted."
else
echo "WARNING: SSH restart not supported on this system."
echo "SSH config applied but service was not restarted automatically."
fi
# Run TNS243-GLOBAL setup
bash /usr/local/bin/menu --install-setup
# Clean up temporary clone (piped execution only)
if [[ -n "$PIPED_CLONE_DIR" ]]; then
rm -rf "$PIPED_CLONE_DIR"
fi
echo "Installation complete!"
echo "Type 'menu' to start."