Hardened dependencies, added space-safe path quoting, and improved Rocky Linux/RHEL 9 support.

This commit is contained in:
SamNet-dev
2026-01-26 01:43:51 -06:00
parent 94522a7b0a
commit 8108be7700

View File

@@ -33,7 +33,7 @@ fi
VERSION="1.0.1" VERSION="1.0.1"
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:d8522a8" CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:d8522a8"
INSTALL_DIR="/opt/conduit" INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
FORCE_REINSTALL=false FORCE_REINSTALL=false
# Colors # Colors
@@ -146,6 +146,11 @@ detect_os() {
fi fi
log_info "Detected: $OS ($OS_FAMILY family), Package manager: $PKG_MANAGER" log_info "Detected: $OS ($OS_FAMILY family), Package manager: $PKG_MANAGER"
if command -v podman &>/dev/null && ! command -v docker &>/dev/null; then
log_warn "Podman detected. This script is optimized for Docker."
log_warn "If installation fails, consider installing 'docker-ce' manually."
fi
} }
install_package() { install_package() {
@@ -154,23 +159,54 @@ install_package() {
case "$PKG_MANAGER" in case "$PKG_MANAGER" in
apt) apt)
apt-get update -qq 2>/dev/null # Make update failure non-fatal but log it
apt-get install -y -qq "$package" 2>/dev/null apt-get update -q || log_warn "apt-get update failed, attempting to install regardless..."
if apt-get install -y -q "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
dnf) dnf)
dnf install -y -q "$package" 2>/dev/null if dnf install -y -q "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
yum) yum)
yum install -y -q "$package" 2>/dev/null if yum install -y -q "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
pacman) pacman)
pacman -Sy --noconfirm "$package" 2>/dev/null if pacman -Sy --noconfirm "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
zypper) zypper)
zypper install -y -n "$package" 2>/dev/null if zypper install -y -n "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
apk) apk)
apk add --no-cache "$package" 2>/dev/null if apk add --no-cache "$package"; then
log_success "$package installed successfully"
else
log_error "Failed to install $package"
return 1
fi
;; ;;
*) *)
log_warn "Unknown package manager. Please install $package manually." log_warn "Unknown package manager. Please install $package manually."
@@ -196,28 +232,28 @@ check_dependencies() {
# Check for basic tools # Check for basic tools
if ! command -v awk &>/dev/null; then if ! command -v awk &>/dev/null; then
case "$PKG_MANAGER" in case "$PKG_MANAGER" in
apt) install_package gawk ;; apt) install_package gawk || log_warn "Could not install gawk" ;;
apk) install_package gawk ;; apk) install_package gawk || log_warn "Could not install gawk" ;;
*) install_package awk ;; *) install_package awk || log_warn "Could not install awk" ;;
esac esac
fi fi
# Check for free command # Check for free command
if ! command -v free &>/dev/null; then if ! command -v free &>/dev/null; then
case "$PKG_MANAGER" in case "$PKG_MANAGER" in
apt|dnf|yum) install_package procps ;; apt|dnf|yum) install_package procps || log_warn "Could not install procps" ;;
pacman) install_package procps-ng ;; pacman) install_package procps-ng || log_warn "Could not install procps" ;;
zypper) install_package procps ;; zypper) install_package procps || log_warn "Could not install procps" ;;
apk) install_package procps ;; apk) install_package procps || log_warn "Could not install procps" ;;
esac esac
fi fi
# Check for tput (ncurses) # Check for tput (ncurses)
if ! command -v tput &>/dev/null; then if ! command -v tput &>/dev/null; then
case "$PKG_MANAGER" in case "$PKG_MANAGER" in
apt) install_package ncurses-bin ;; apt) install_package ncurses-bin || log_warn "Could not install ncurses-bin" ;;
apk) install_package ncurses ;; apk) install_package ncurses || log_warn "Could not install ncurses" ;;
*) install_package ncurses ;; *) install_package ncurses || log_warn "Could not install ncurses" ;;
esac esac
fi fi
@@ -229,18 +265,22 @@ check_dependencies() {
# Check for GeoIP tools # Check for GeoIP tools
if ! command -v geoiplookup &>/dev/null; then if ! command -v geoiplookup &>/dev/null; then
case "$PKG_MANAGER" in case "$PKG_MANAGER" in
apt) install_package geoip-bin ;; apt)
# geoip-bin is becoming legacy in some Ubuntu versions, but still works in many.
# If it fails, we warn but don't stop the whole script if other things work.
install_package geoip-bin || log_warn "Could not install geoip-bin. Live peer map may not show countries."
;;
dnf|yum) dnf|yum)
# On RHEL/CentOS # On RHEL/CentOS
if ! rpm -q epel-release &>/dev/null; then if ! rpm -q epel-release &>/dev/null; then
log_info "Enabling EPEL repository for GeoIP..." log_info "Enabling EPEL repository for GeoIP..."
$PKG_MANAGER install -y epel-release &>/dev/null || true $PKG_MANAGER install -y epel-release &>/dev/null || true
fi fi
install_package GeoIP install_package GeoIP || log_warn "Could not install GeoIP."
;; ;;
pacman) install_package geoip ;; pacman) install_package geoip || log_warn "Could not install geoip." ;;
zypper) install_package GeoIP ;; zypper) install_package GeoIP || log_warn "Could not install GeoIP." ;;
apk) install_package geoip ;; apk) install_package geoip || log_warn "Could not install geoip." ;;
*) log_warn "Could not install geoiplookup automatically" ;; *) log_warn "Could not install geoiplookup automatically" ;;
esac esac
fi fi
@@ -413,6 +453,13 @@ install_docker() {
log_info "Installing Docker..." log_info "Installing Docker..."
# Check OS family for specific requirements
if [ "$OS_FAMILY" = "rhel" ]; then
log_info "Installing RHEL-specific Docker dependencies..."
$PKG_MANAGER install -y -q dnf-plugins-core 2>/dev/null || true
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || true
fi
# Alpine # Alpine
if [ "$OS_FAMILY" = "alpine" ]; then if [ "$OS_FAMILY" = "alpine" ]; then
apk add --no-cache docker docker-cli-compose 2>/dev/null apk add --no-cache docker docker-cli-compose 2>/dev/null
@@ -420,7 +467,11 @@ install_docker() {
service docker start 2>/dev/null || rc-service docker start 2>/dev/null || true service docker start 2>/dev/null || rc-service docker start 2>/dev/null || true
else else
# Use official Docker install # Use official Docker install
curl -fsSL https://get.docker.com | sh if ! curl -fsSL https://get.docker.com | sh; then
log_error "Official Docker installation script failed."
log_info "Try installing docker manually: https://docs.docker.com/engine/install/"
return 1
fi
# Enable and start Docker # Enable and start Docker
if [ "$HAS_SYSTEMD" = "true" ]; then if [ "$HAS_SYSTEMD" = "true" ]; then
@@ -458,7 +509,14 @@ install_docker() {
run_conduit() { run_conduit() {
log_info "Starting Conduit container..." log_info "Starting Conduit container..."
# Stop existing container # Check for existing conduit containers (any image containing conduit)
local existing=$(docker ps -a --filter "ancestor=ghcr.io/ssmirr/conduit/conduit" --format "{{.Names}}")
if [ -n "$existing" ] && [ "$existing" != "conduit" ]; then
log_warn "Detected other Conduit containers: $existing"
log_warn "Running multiple instances may cause port conflicts."
fi
# Stop existing container with our name
docker rm -f conduit 2>/dev/null || true docker rm -f conduit 2>/dev/null || true
# Pull image # Pull image
@@ -494,7 +552,7 @@ run_conduit() {
} }
save_settings() { save_settings() {
mkdir -p $INSTALL_DIR mkdir -p "$INSTALL_DIR"
# Save settings # Save settings
cat > "$INSTALL_DIR/settings.conf" << EOF cat > "$INSTALL_DIR/settings.conf" << EOF
@@ -515,7 +573,8 @@ setup_autostart() {
if [ "$HAS_SYSTEMD" = "true" ]; then if [ "$HAS_SYSTEMD" = "true" ]; then
# Systemd-based systems # Systemd-based systems
cat > /etc/systemd/system/conduit.service << 'EOF' local docker_path=$(command -v docker)
cat > /etc/systemd/system/conduit.service << EOF
[Unit] [Unit]
Description=Psiphon Conduit Service Description=Psiphon Conduit Service
After=network.target docker.service After=network.target docker.service
@@ -524,8 +583,8 @@ Requires=docker.service
[Service] [Service]
Type=oneshot Type=oneshot
RemainAfterExit=yes RemainAfterExit=yes
ExecStart=/usr/bin/docker start conduit ExecStart=$docker_path start conduit
ExecStop=/usr/bin/docker stop conduit ExecStop=$docker_path stop conduit
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
@@ -613,7 +672,10 @@ EOF
#═══════════════════════════════════════════════════════════════════════ #═══════════════════════════════════════════════════════════════════════
create_management_script() { create_management_script() {
cat > $INSTALL_DIR/conduit << 'MANAGEMENT' # Generate the management script.
# Note: We use a placeholder for INSTALL_DIR that we'll replace with sed
# to avoid complex escaping in the heredoc while keeping it dynamic.
cat > "$INSTALL_DIR/conduit" << 'MANAGEMENT'
#!/bin/bash #!/bin/bash
# #
# Psiphon Conduit Manager # Psiphon Conduit Manager
@@ -621,7 +683,7 @@ create_management_script() {
# #
VERSION="1.0.1" VERSION="1.0.1"
INSTALL_DIR="/opt/conduit" INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:d8522a8" CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:d8522a8"
# Colors # Colors
@@ -957,7 +1019,7 @@ show_peers() {
echo -ne "\033[?25h" # Show cursor echo -ne "\033[?25h" # Show cursor
tput rmcup 2>/dev/null || true tput rmcup 2>/dev/null || true
rm -f /tmp/conduit_peers_current rm -f /tmp/conduit_peers_current /tmp/conduit_peers_next
trap - SIGINT SIGTERM trap - SIGINT SIGTERM
} }
@@ -1196,7 +1258,7 @@ change_settings() {
fi fi
# Save settings # Save settings
cat > $INSTALL_DIR/settings.conf << EOF cat > "$INSTALL_DIR/settings.conf" << EOF
MAX_CLIENTS=$MAX_CLIENTS MAX_CLIENTS=$MAX_CLIENTS
BANDWIDTH=$BANDWIDTH BANDWIDTH=$BANDWIDTH
EOF EOF
@@ -1261,19 +1323,19 @@ uninstall_all() {
fi fi
echo "" echo ""
echo "[INFO] Stopping Conduit container..." echo -e "${BLUE}[INFO]${NC} Stopping Conduit container..."
docker stop conduit 2>/dev/null || true docker stop conduit 2>/dev/null || true
echo "[INFO] Removing Conduit container..." echo -e "${BLUE}[INFO]${NC} Removing Conduit container..."
docker rm -f conduit 2>/dev/null || true docker rm -f conduit 2>/dev/null || true
echo "[INFO] Removing Conduit Docker image..." echo -e "${BLUE}[INFO]${NC} Removing Conduit Docker image..."
docker rmi $CONDUIT_IMAGE 2>/dev/null || true docker rmi "$CONDUIT_IMAGE" 2>/dev/null || true
echo "[INFO] Removing Conduit data volume..." echo -e "${BLUE}[INFO]${NC} Removing Conduit data volume..."
docker volume rm conduit-data 2>/dev/null || true docker volume rm conduit-data 2>/dev/null || true
echo "[INFO] Removing auto-start service..." echo -e "${BLUE}[INFO]${NC} Removing auto-start service..."
# Systemd # Systemd
systemctl stop conduit.service 2>/dev/null || true systemctl stop conduit.service 2>/dev/null || true
systemctl disable conduit.service 2>/dev/null || true systemctl disable conduit.service 2>/dev/null || true
@@ -1287,8 +1349,8 @@ uninstall_all() {
chkconfig conduit off 2>/dev/null || true chkconfig conduit off 2>/dev/null || true
rm -f /etc/init.d/conduit rm -f /etc/init.d/conduit
echo "[INFO] Removing configuration files..." echo -e "${BLUE}[INFO]${NC} Removing configuration files..."
rm -rf /opt/conduit rm -rf "$INSTALL_DIR"
rm -f /usr/local/bin/conduit rm -f /usr/local/bin/conduit
echo "" echo ""
@@ -1298,8 +1360,7 @@ uninstall_all() {
echo "" echo ""
echo "Conduit and all related components have been removed." echo "Conduit and all related components have been removed."
echo "" echo ""
echo "Note: Docker itself was NOT removed. To remove Docker:" echo "Note: Docker itself was NOT removed."
echo " apt-get purge docker-ce docker-ce-cli containerd.io"
echo "" echo ""
} }
@@ -1421,10 +1482,14 @@ case "${1:-menu}" in
esac esac
MANAGEMENT MANAGEMENT
chmod +x $INSTALL_DIR/conduit # Patch the INSTALL_DIR in the generated script
# Use # as delimiter to avoid issues if path contains /
sed -i "s#REPLACE_ME_INSTALL_DIR#$INSTALL_DIR#g" "$INSTALL_DIR/conduit"
chmod +x "$INSTALL_DIR/conduit"
# Force create symlink # Force create symlink
rm -f /usr/local/bin/conduit 2>/dev/null || true rm -f /usr/local/bin/conduit 2>/dev/null || true
ln -s $INSTALL_DIR/conduit /usr/local/bin/conduit ln -s "$INSTALL_DIR/conduit" /usr/local/bin/conduit
log_success "Management script installed: conduit" log_success "Management script installed: conduit"
} }
@@ -1479,11 +1544,10 @@ print_summary() {
#═══════════════════════════════════════════════════════════════════════ #═══════════════════════════════════════════════════════════════════════
uninstall() { uninstall() {
echo -e "${CYAN}" echo ""
echo "╔═══════════════════════════════════════════════════════════════════╗" echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════════╗${NC}"
echo "║ ⚠️ UNINSTALL CONDUIT ║" echo "║ ⚠️ UNINSTALL CONDUIT ║"
echo "╚═══════════════════════════════════════════════════════════════════╝" echo "╚═══════════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo "" echo ""
echo "This will completely remove:" echo "This will completely remove:"
echo " • Conduit Docker container" echo " • Conduit Docker container"
@@ -1510,7 +1574,7 @@ uninstall() {
docker rm -f conduit 2>/dev/null || true docker rm -f conduit 2>/dev/null || true
log_info "Removing Conduit Docker image..." log_info "Removing Conduit Docker image..."
docker rmi ghcr.io/ssmirr/conduit/conduit:latest 2>/dev/null || true docker rmi "$CONDUIT_IMAGE" 2>/dev/null || true
log_info "Removing Conduit data volume..." log_info "Removing Conduit data volume..."
docker volume rm conduit-data 2>/dev/null || true docker volume rm conduit-data 2>/dev/null || true
@@ -1530,7 +1594,7 @@ uninstall() {
rm -f /etc/init.d/conduit rm -f /etc/init.d/conduit
log_info "Removing configuration files..." log_info "Removing configuration files..."
rm -rf /opt/conduit rm -rf "$INSTALL_DIR"
rm -f /usr/local/bin/conduit rm -f /usr/local/bin/conduit
echo "" echo ""
@@ -1540,8 +1604,7 @@ uninstall() {
echo "" echo ""
echo "Conduit and all related components have been removed." echo "Conduit and all related components have been removed."
echo "" echo ""
echo "Note: Docker itself was NOT removed. To remove Docker:" echo "Note: Docker itself was NOT removed."
echo " apt-get purge docker-ce docker-ce-cli containerd.io"
echo "" echo ""
} }
@@ -1610,7 +1673,7 @@ main() {
1) 1)
echo -e "${CYAN}Opening management menu...${NC}" echo -e "${CYAN}Opening management menu...${NC}"
create_management_script >/dev/null 2>&1 create_management_script >/dev/null 2>&1
exec /opt/conduit/conduit menu exec "$INSTALL_DIR/conduit" menu
;; ;;
2) 2)
echo "" echo ""
@@ -1661,7 +1724,7 @@ main() {
read -p "View live statistics now? [Y/n] " view_stats < /dev/tty || true read -p "View live statistics now? [Y/n] " view_stats < /dev/tty || true
if [[ ! "$view_stats" =~ ^[Nn] ]]; then if [[ ! "$view_stats" =~ ^[Nn] ]]; then
/opt/conduit/conduit stats "$INSTALL_DIR/conduit" stats
fi fi
} }
# #