From f2579718ae35bd2cd8cfbeef19109a8f875e9e67 Mon Sep 17 00:00:00 2001 From: SamNet-dev <98samh@gmail.com> Date: Sun, 25 Jan 2026 12:54:06 -0600 Subject: [PATCH] Delete install.sh Removed redundant 'install.sh'. 'conduit.sh' now handles all installation, updates, and management tasks, effectively replacing the outdated install script. --- install.sh | 1280 ---------------------------------------------------- 1 file changed, 1280 deletions(-) delete mode 100644 install.sh diff --git a/install.sh b/install.sh deleted file mode 100644 index de79576..0000000 --- a/install.sh +++ /dev/null @@ -1,1280 +0,0 @@ -#!/bin/bash -# Updated: 2026-01-24 06:01 UTC -# -# ╔═══════════════════════════════════════════════════════════════════╗ -# ║ 🚀 PSIPHON CONDUIT MANAGER v1.0.0 ║ -# ║ ║ -# ║ One-click setup for Psiphon Conduit ║ -# ║ ║ -# ║ • Installs Docker (if needed) ║ -# ║ • Runs Conduit in Docker with live stats ║ -# ║ • Auto-start on boot via systemd/OpenRC/SysVinit ║ -# ║ • Easy management via CLI or interactive menu ║ -# ║ ║ -# ║ GitHub: https://github.com/Psiphon-Inc/conduit ║ -# ╚═══════════════════════════════════════════════════════════════════╝ -# -# Usage: -# curl -sL https://your-url/conduit.sh | sudo bash -# -# Reference: https://github.com/ssmirr/conduit/releases/tag/87cc1a3 -# Conduit CLI options: -# -m, --max-clients int maximum number of proxy clients (1-1000) (default 200) -# -b, --bandwidth float bandwidth limit per peer in Mbps (1-40) (default 5) -# -v, --verbose increase verbosity (-v for verbose, -vv for debug) -# - -set -e - -# Ensure we're running in bash (not sh/dash) -if [ -z "$BASH_VERSION" ]; then - echo "Error: This script requires bash. Please run with: bash $0" - exit 1 -fi - -VERSION="1.0.0" -CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:87cc1a3" -INSTALL_DIR="/opt/conduit" -FORCE_REINSTALL=false - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -BOLD='\033[1m' -NC='\033[0m' # No Color - -#═══════════════════════════════════════════════════════════════════════ -# Utility Functions -#═══════════════════════════════════════════════════════════════════════ - -print_header() { - echo -e "${CYAN}" - echo "╔═══════════════════════════════════════════════════════════════════╗" - echo "║ 🚀 PSIPHON CONDUIT MANAGER v${VERSION} ║" - echo "╠═══════════════════════════════════════════════════════════════════╣" - echo "║ Help users access the open internet during shutdowns ║" - echo "╚═══════════════════════════════════════════════════════════════════╝" - echo -e "${NC}" -} - -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[✓]${NC} $1" -} - -log_warn() { - echo -e "${YELLOW}[!]${NC} $1" -} - -log_error() { - echo -e "${RED}[✗]${NC} $1" -} - -check_root() { - if [ "$EUID" -ne 0 ]; then - log_error "This script must be run as root (use sudo)" - exit 1 - fi -} - -detect_os() { - OS="unknown" - OS_VERSION="unknown" - OS_FAMILY="unknown" - HAS_SYSTEMD=false - PKG_MANAGER="unknown" - - # Detect OS from /etc/os-release (most modern distros) - if [ -f /etc/os-release ]; then - . /etc/os-release - OS="$ID" - OS_VERSION="${VERSION_ID:-unknown}" - elif [ -f /etc/redhat-release ]; then - OS="rhel" - elif [ -f /etc/debian_version ]; then - OS="debian" - elif [ -f /etc/alpine-release ]; then - OS="alpine" - elif [ -f /etc/arch-release ]; then - OS="arch" - elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then - OS="opensuse" - else - OS=$(uname -s | tr '[:upper:]' '[:lower:]') - fi - - # Determine OS family and package manager - case "$OS" in - ubuntu|debian|linuxmint|pop|elementary|zorin|kali|raspbian) - OS_FAMILY="debian" - PKG_MANAGER="apt" - ;; - rhel|centos|fedora|rocky|almalinux|oracle|amazon|amzn) - OS_FAMILY="rhel" - if command -v dnf &>/dev/null; then - PKG_MANAGER="dnf" - else - PKG_MANAGER="yum" - fi - ;; - arch|manjaro|endeavouros|garuda) - OS_FAMILY="arch" - PKG_MANAGER="pacman" - ;; - opensuse|opensuse-leap|opensuse-tumbleweed|sles) - OS_FAMILY="suse" - PKG_MANAGER="zypper" - ;; - alpine) - OS_FAMILY="alpine" - PKG_MANAGER="apk" - ;; - *) - OS_FAMILY="unknown" - PKG_MANAGER="unknown" - ;; - esac - - # Check for systemd - if command -v systemctl &>/dev/null && [ -d /run/systemd/system ]; then - HAS_SYSTEMD=true - fi - - log_info "Detected: $OS ($OS_FAMILY family), Package manager: $PKG_MANAGER" -} - -install_package() { - local package="$1" - log_info "Installing $package..." - - case "$PKG_MANAGER" in - apt) - apt-get update -qq 2>/dev/null - apt-get install -y -qq "$package" 2>/dev/null - ;; - dnf) - dnf install -y -q "$package" 2>/dev/null - ;; - yum) - yum install -y -q "$package" 2>/dev/null - ;; - pacman) - pacman -Sy --noconfirm "$package" 2>/dev/null - ;; - zypper) - zypper install -y -n "$package" 2>/dev/null - ;; - apk) - apk add --no-cache "$package" 2>/dev/null - ;; - *) - log_warn "Unknown package manager. Please install $package manually." - return 1 - ;; - esac -} - -check_dependencies() { - # Check for bash (Alpine uses ash by default) - if [ "$OS_FAMILY" = "alpine" ]; then - if ! command -v bash &>/dev/null; then - log_info "Installing bash (required for this script)..." - apk add --no-cache bash 2>/dev/null - fi - fi - - # Check for curl - if ! command -v curl &>/dev/null; then - install_package curl || log_warn "Could not install curl automatically" - fi - - # Check for basic tools - if ! command -v awk &>/dev/null; then - case "$PKG_MANAGER" in - apt) install_package gawk ;; - apk) install_package gawk ;; - *) install_package awk ;; - esac - fi - - # Check for free command (part of procps) - if ! command -v free &>/dev/null; then - case "$PKG_MANAGER" in - apt|dnf|yum) install_package procps ;; - pacman) install_package procps-ng ;; - zypper) install_package procps ;; - apk) install_package procps ;; - esac - fi -} - -get_ram_gb() { - # Get RAM in GB, minimum 1 for safety - local ram="" - - # Try free command first - if command -v free &>/dev/null; then - ram=$(free -g 2>/dev/null | awk '/^Mem:/{print $2}') - fi - - # Fallback: parse /proc/meminfo - if [ -z "$ram" ] || [ "$ram" = "0" ]; then - if [ -f /proc/meminfo ]; then - local kb=$(awk '/^MemTotal:/{print $2}' /proc/meminfo 2>/dev/null) - if [ -n "$kb" ]; then - ram=$((kb / 1024 / 1024)) - fi - fi - fi - - # Ensure minimum of 1 - if [ -z "$ram" ] || [ "$ram" -lt 1 ] 2>/dev/null; then - echo 1 - else - echo "$ram" - fi -} - -calculate_recommended_clients() { - local ram_gb=$(get_ram_gb) - - if [ "$ram_gb" -ge 8 ]; then - echo 1000 - elif [ "$ram_gb" -ge 4 ]; then - echo 700 - elif [ "$ram_gb" -ge 2 ]; then - echo 400 - else - echo 200 - fi -} - -#═══════════════════════════════════════════════════════════════════════ -# Interactive Setup -#═══════════════════════════════════════════════════════════════════════ - -prompt_settings() { - local ram_gb=$(get_ram_gb) - local recommended=$(calculate_recommended_clients) - - echo "" - echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" - echo -e "${CYAN} CONDUIT CONFIGURATION ${NC}" - echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" - echo "" - echo -e " ${BOLD}Server Info:${NC}" - echo -e " RAM: ${GREEN}${ram_gb}GB${NC}" - echo -e " Recommended max-clients: ${GREEN}${recommended}${NC}" - echo "" - echo -e " ${BOLD}Conduit Options:${NC}" - echo -e " ${YELLOW}--max-clients${NC} Maximum proxy clients (1-1000)" - echo -e " ${YELLOW}--bandwidth${NC} Bandwidth per peer in Mbps (1-40)" - echo "" - - # Max clients prompt - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - echo -e " Enter max-clients (1-1000)" - echo -e " Press Enter for recommended: ${GREEN}${recommended}${NC}" - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - read -p " max-clients: " input_clients < /dev/tty || true - - if [ -z "$input_clients" ]; then - MAX_CLIENTS=$recommended - elif [[ "$input_clients" =~ ^[0-9]+$ ]] && [ "$input_clients" -ge 1 ] && [ "$input_clients" -le 1000 ]; then - MAX_CLIENTS=$input_clients - else - log_warn "Invalid input. Using recommended: $recommended" - MAX_CLIENTS=$recommended - fi - - echo "" - - # Bandwidth prompt - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - echo -e " Enter bandwidth per peer in Mbps (1-40)" - echo -e " Press Enter for default: ${GREEN}5${NC} Mbps" - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - read -p " bandwidth: " input_bandwidth < /dev/tty || true - - if [ -z "$input_bandwidth" ]; then - BANDWIDTH=5 - elif [[ "$input_bandwidth" =~ ^[0-9]+$ ]] && [ "$input_bandwidth" -ge 1 ] && [ "$input_bandwidth" -le 40 ]; then - BANDWIDTH=$input_bandwidth - elif [[ "$input_bandwidth" =~ ^[0-9]*\.[0-9]+$ ]]; then - # Handle decimal - validate the whole number is in range - local float_ok=$(awk -v val="$input_bandwidth" 'BEGIN { print (val >= 1 && val <= 40) ? "yes" : "no" }') - if [ "$float_ok" = "yes" ]; then - BANDWIDTH=$input_bandwidth - else - log_warn "Invalid input. Using default: 5 Mbps" - BANDWIDTH=5 - fi - else - log_warn "Invalid input. Using default: 5 Mbps" - BANDWIDTH=5 - fi - - echo "" - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - echo -e " ${BOLD}Your Settings:${NC}" - echo -e " Max Clients: ${GREEN}${MAX_CLIENTS}${NC}" - echo -e " Bandwidth: ${GREEN}${BANDWIDTH}${NC} Mbps" - echo -e "${CYAN}───────────────────────────────────────────────────────────────${NC}" - echo "" - - read -p " Proceed with these settings? [Y/n] " confirm < /dev/tty || true - if [[ "$confirm" =~ ^[Nn] ]]; then - prompt_settings - fi -} - -#═══════════════════════════════════════════════════════════════════════ -# Installation Functions -#═══════════════════════════════════════════════════════════════════════ - -install_docker() { - if command -v docker &>/dev/null; then - log_success "Docker is already installed" - return 0 - fi - - log_info "Installing Docker..." - - # Alpine uses a different method - if [ "$OS_FAMILY" = "alpine" ]; then - apk add --no-cache docker docker-cli-compose 2>/dev/null - rc-update add docker boot 2>/dev/null || true - service docker start 2>/dev/null || rc-service docker start 2>/dev/null || true - else - # Use official Docker install script for most distros - curl -fsSL https://get.docker.com | sh - - # Enable and start Docker - if [ "$HAS_SYSTEMD" = "true" ]; then - systemctl enable docker 2>/dev/null || true - systemctl start docker 2>/dev/null || true - else - # Fallback for non-systemd (SysVinit, OpenRC, etc.) - if command -v update-rc.d &>/dev/null; then - update-rc.d docker defaults 2>/dev/null || true - elif command -v chkconfig &>/dev/null; then - chkconfig docker on 2>/dev/null || true - elif command -v rc-update &>/dev/null; then - rc-update add docker default 2>/dev/null || true - fi - service docker start 2>/dev/null || /etc/init.d/docker start 2>/dev/null || true - fi - fi - - # Wait for Docker to be ready (up to 30 seconds for slow systems) - sleep 3 - local retries=27 - while ! docker info &>/dev/null && [ $retries -gt 0 ]; do - sleep 1 - retries=$((retries - 1)) - done - - if docker info &>/dev/null; then - log_success "Docker installed successfully" - else - log_error "Docker installation may have failed. Please check manually." - return 1 - fi -} - -run_conduit() { - log_info "Starting Conduit container..." - - # Stop existing container - docker rm -f conduit 2>/dev/null || true - - # Pull latest image - log_info "Pulling Conduit image from ghcr.io/ssmirr/conduit..." - if ! docker pull $CONDUIT_IMAGE; then - log_error "Failed to pull Conduit image. Check your internet connection." - exit 1 - fi - - # Run container with host networking - docker run -d \ - --name conduit \ - --restart unless-stopped \ - -v conduit-data:/home/conduit/data \ - --network host \ - $CONDUIT_IMAGE \ - start --max-clients "$MAX_CLIENTS" --bandwidth "$BANDWIDTH" -v - - sleep 3 - - if docker ps | grep -q conduit; then - log_success "Conduit container is running" - log_success "Settings: max-clients=$MAX_CLIENTS, bandwidth=${BANDWIDTH}Mbps" - else - log_error "Conduit failed to start" - docker logs conduit 2>&1 | tail -10 - exit 1 - fi -} - -save_settings() { - mkdir -p $INSTALL_DIR - - # Save settings - cat > "$INSTALL_DIR/settings.conf" << EOF -MAX_CLIENTS=$MAX_CLIENTS -BANDWIDTH=$BANDWIDTH -EOF - - # Verify write succeeded - if [ ! -f "$INSTALL_DIR/settings.conf" ]; then - log_error "Failed to save settings. Check disk space and permissions." - return 1 - fi - - log_success "Settings saved" -} - -setup_autostart() { - log_info "Setting up auto-start on boot..." - - if [ "$HAS_SYSTEMD" = "true" ]; then - # Systemd-based systems - cat > /etc/systemd/system/conduit.service << 'EOF' -[Unit] -Description=Psiphon Conduit Service -After=network.target docker.service -Requires=docker.service - -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=/usr/bin/docker start conduit -ExecStop=/usr/bin/docker stop conduit - -[Install] -WantedBy=multi-user.target -EOF - - systemctl daemon-reload - systemctl enable conduit.service 2>/dev/null || true - systemctl start conduit.service 2>/dev/null || true - log_success "Systemd service created, enabled, and started" - - elif command -v rc-update &>/dev/null; then - # OpenRC (Alpine, Gentoo, etc.) - cat > /etc/init.d/conduit << 'EOF' -#!/sbin/openrc-run - -name="conduit" -description="Psiphon Conduit Service" -depend() { - need docker - after network -} -start() { - ebegin "Starting Conduit" - docker start conduit - eend $? -} -stop() { - ebegin "Stopping Conduit" - docker stop conduit - eend $? -} -EOF - chmod +x /etc/init.d/conduit - rc-update add conduit default 2>/dev/null || true - log_success "OpenRC service created and enabled" - - elif [ -d /etc/init.d ]; then - # SysVinit fallback - cat > /etc/init.d/conduit << 'EOF' -#!/bin/sh -### BEGIN INIT INFO -# Provides: conduit -# Required-Start: $docker -# Required-Stop: $docker -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Psiphon Conduit Service -### END INIT INFO - -case "$1" in - start) - docker start conduit - ;; - stop) - docker stop conduit - ;; - restart) - docker restart conduit - ;; - status) - docker ps | grep -q conduit && echo "Running" || echo "Stopped" - ;; - *) - echo "Usage: $0 {start|stop|restart|status}" - exit 1 - ;; -esac -EOF - chmod +x /etc/init.d/conduit - if command -v update-rc.d &>/dev/null; then - update-rc.d conduit defaults 2>/dev/null || true - elif command -v chkconfig &>/dev/null; then - chkconfig conduit on 2>/dev/null || true - fi - log_success "SysVinit service created and enabled" - - else - log_warn "Could not set up auto-start. Docker's restart policy will handle restarts." - log_info "Container is set to restart unless-stopped, which works on reboot if Docker starts." - fi -} - -#═══════════════════════════════════════════════════════════════════════ -# Management Script -#═══════════════════════════════════════════════════════════════════════ - -create_management_script() { - cat > $INSTALL_DIR/conduit << 'MANAGEMENT' -#!/bin/bash -# -# Psiphon Conduit Manager -# Reference: https://github.com/ssmirr/conduit/releases/tag/87cc1a3 -# - -VERSION="1.0.0" -INSTALL_DIR="/opt/conduit" -CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:87cc1a3" - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -BOLD='\033[1m' -NC='\033[0m' - -# Load settings -[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf" -MAX_CLIENTS=${MAX_CLIENTS:-200} -BANDWIDTH=${BANDWIDTH:-5} - -# Check if Docker is available -check_docker() { - if ! command -v docker &>/dev/null; then - echo -e "${RED}Error: Docker is not installed!${NC}" - echo "" - echo "Docker is required to run Conduit. Please reinstall:" - echo " curl -fsSL https://get.docker.com | sudo sh" - echo "" - echo "Or re-run the Conduit installer:" - echo " sudo bash conduit.sh" - exit 1 - fi - - if ! docker info &>/dev/null; then - echo -e "${RED}Error: Docker daemon is not running!${NC}" - echo "" - echo "Start Docker with:" - echo " sudo systemctl start docker # For systemd" - echo " sudo /etc/init.d/docker start # For SysVinit" - echo " sudo rc-service docker start # For OpenRC" - exit 1 - fi -} - -# Run Docker check -check_docker - -# Check for awk (needed for stats parsing) -if ! command -v awk &>/dev/null; then - echo -e "${YELLOW}Warning: awk not found. Some stats may not display correctly.${NC}" -fi - -print_header() { - echo -e "${CYAN}" - echo "╔═══════════════════════════════════════════════════════════════════╗" - echo "║ 🚀 PSIPHON CONDUIT MANAGER v${VERSION} ║" - echo "╚═══════════════════════════════════════════════════════════════════╝" - echo -e "${NC}" -} - -print_live_stats_header() { - echo -e "${CYAN}" - echo "╔═══════════════════════════════════════════════════════════════════╗" - echo "║ CONDUIT LIVE STATISTICS ║" - echo "╠═══════════════════════════════════════════════════════════════════╣" - echo -e "║ Max Clients: ${GREEN}${MAX_CLIENTS}${CYAN} ║" - echo -e "║ Bandwidth: ${GREEN}${BANDWIDTH} Mbps${CYAN} ║" - echo "║ ║" - echo "║ Press Ctrl+C to exit ║" - echo "╚═══════════════════════════════════════════════════════════════════╝" - echo -e "${NC}" -} - -get_container_resources() { - # Get CPU and memory usage from docker stats - if docker ps 2>/dev/null | grep -q "[[:space:]]conduit$"; then - local stats=$(docker stats conduit --no-stream --format "{{.CPUPerc}}|{{.MemUsage}}|{{.MemPerc}}" 2>/dev/null) - if [ -n "$stats" ]; then - CPU_USAGE=$(echo "$stats" | cut -d'|' -f1) - MEM_USAGE=$(echo "$stats" | cut -d'|' -f2) - MEM_PERC=$(echo "$stats" | cut -d'|' -f3) - else - CPU_USAGE="N/A" - MEM_USAGE="N/A" - MEM_PERC="N/A" - fi - else - CPU_USAGE="N/A" - MEM_USAGE="N/A" - MEM_PERC="N/A" - fi -} - -show_dashboard() { - local stop_dashboard=0 - # Setup trap to catch signals gracefully - trap 'stop_dashboard=1' SIGINT SIGTERM - - echo -ne "\033[?25l" # Hide cursor - clear - - while [ $stop_dashboard -eq 0 ]; do - echo -ne "\033[H" # Move cursor to top-left - print_live_stats_header - - show_status - - # Get and show resource usage - get_container_resources - echo "" - echo -e "${CYAN}═══ RESOURCE USAGE ═══${NC}" - echo -e " CPU: ${YELLOW}${CPU_USAGE}${NC}" - echo -e " Memory: ${YELLOW}${MEM_USAGE}${NC} (${MEM_PERC})" - echo "" - echo -e "${BOLD}Refreshes every 10 seconds. Press any key to return to menu...${NC}" - - # Clear any leftover content below - tput ed 2>/dev/null || true - - # Wait 10 seconds for keypress. Signal will interrupt this read. - if read -t 10 -n 1; then - stop_dashboard=1 - fi - done - - echo -ne "\033[?25h" # Show cursor - trap - SIGINT SIGTERM # Reset traps -} - -show_live_stats() { - print_header - echo -e "${YELLOW}Reading traffic history...${NC}" - echo -e "${CYAN}Press Ctrl+C to return to menu${NC}" - echo "" - # Stream logs, filter for [STATS], and strip everything before [STATS] - docker logs -f --tail 200 conduit 2>&1 | grep --line-buffered "\[STATS\]" | sed -u -e 's/.*\[STATS\]/[STATS]/' -} - -show_status() { - echo "" - echo -e "${CYAN}═══ CONDUIT STATUS ═══${NC}" - - if docker ps 2>/dev/null | grep -q "[[:space:]]conduit$"; then - echo -e " Container: ${GREEN}Running${NC}" - - # Get last stats from logs - local stats=$(docker logs --tail 100 conduit 2>&1 | grep "STATS" | tail -1) - if [ -n "$stats" ]; then - local connected=$(echo "$stats" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p') - local upload=$(echo "$stats" | sed -n 's/.*Up:[[:space:]]*\([^|]*\).*/\1/p' | tr -d ' ') - local download=$(echo "$stats" | sed -n 's/.*Down:[[:space:]]*\([^|]*\).*/\1/p' | tr -d ' ') - [ -n "$connected" ] && echo -e " Clients: ${GREEN}${connected}${NC} connected" - [ -n "$upload" ] && echo -e " Upload: ${upload}" - [ -n "$download" ] && echo -e " Download: ${download}" - else - echo -e " Stats: ${YELLOW}Waiting for first stats...${NC}" - fi - - else - echo -e " Container: ${RED}Stopped${NC}" - fi - - echo "" - echo -e "${CYAN}═══ SETTINGS ═══${NC}" - echo -e " Max Clients: ${MAX_CLIENTS}" - echo -e " Bandwidth: ${BANDWIDTH} Mbps" - - echo "" - echo -e "${CYAN}═══ AUTO-START SERVICE ═══${NC}" - # Check for systemd - if command -v systemctl &>/dev/null && systemctl is-enabled conduit.service 2>/dev/null | grep -q "enabled"; then - echo -e " Auto-start: ${GREEN}Enabled (systemd)${NC}" - local svc_status=$(systemctl is-active conduit.service 2>/dev/null) - echo -e " Service: ${svc_status:-unknown}" - # Check for OpenRC - elif command -v rc-status &>/dev/null && rc-status -a 2>/dev/null | grep -q "conduit"; then - echo -e " Auto-start: ${GREEN}Enabled (OpenRC)${NC}" - # Check for SysVinit - elif [ -f /etc/init.d/conduit ]; then - echo -e " Auto-start: ${GREEN}Enabled (SysVinit)${NC}" - else - echo -e " Auto-start: ${YELLOW}Not configured${NC}" - echo -e " Note: Docker restart policy handles restarts" - fi - echo "" -} - -start_conduit() { - echo "Starting Conduit..." - if docker ps -a 2>/dev/null | grep -q "[[:space:]]conduit$"; then - if docker start conduit 2>/dev/null; then - echo -e "${GREEN}✓ Conduit started${NC}" - else - echo -e "${RED}✗ Failed to start Conduit${NC}" - return 1 - fi - else - echo "Container not found. Creating new container..." - docker run -d \ - --name conduit \ - --restart unless-stopped \ - -v conduit-data:/home/conduit/data \ - --network host \ - $CONDUIT_IMAGE \ - start --max-clients "$MAX_CLIENTS" --bandwidth "$BANDWIDTH" -v - if [ $? -eq 0 ]; then - echo -e "${GREEN}✓ Conduit started${NC}" - else - echo -e "${RED}✗ Failed to start Conduit${NC}" - return 1 - fi - fi -} - -stop_conduit() { - echo "Stopping Conduit..." - if docker ps 2>/dev/null | grep -q "[[:space:]]conduit$"; then - docker stop conduit 2>/dev/null - echo -e "${YELLOW}✓ Conduit stopped${NC}" - else - echo -e "${YELLOW}Conduit is not running${NC}" - fi -} - -restart_conduit() { - echo "Restarting Conduit..." - if docker ps -a 2>/dev/null | grep -q "[[:space:]]conduit$"; then - docker restart conduit 2>/dev/null - echo -e "${GREEN}✓ Conduit restarted${NC}" - else - echo -e "${RED}Conduit container not found. Use 'conduit start' to create it.${NC}" - return 1 - fi -} - -change_settings() { - echo "" - echo -e "${CYAN}Current Settings:${NC}" - echo -e " Max Clients: ${MAX_CLIENTS}" - echo -e " Bandwidth: ${BANDWIDTH} Mbps" - echo "" - - read -p "New max-clients (1-1000) [${MAX_CLIENTS}]: " new_clients < /dev/tty || true - read -p "New bandwidth in Mbps (1-40) [${BANDWIDTH}]: " new_bandwidth < /dev/tty || true - - # Validate max-clients - if [ -n "$new_clients" ]; then - if [[ "$new_clients" =~ ^[0-9]+$ ]] && [ "$new_clients" -ge 1 ] && [ "$new_clients" -le 1000 ]; then - MAX_CLIENTS=$new_clients - else - echo -e "${YELLOW}Invalid max-clients. Keeping current: ${MAX_CLIENTS}${NC}" - fi - fi - - # Validate bandwidth - if [ -n "$new_bandwidth" ]; then - if [[ "$new_bandwidth" =~ ^[0-9]+$ ]] && [ "$new_bandwidth" -ge 1 ] && [ "$new_bandwidth" -le 40 ]; then - BANDWIDTH=$new_bandwidth - elif [[ "$new_bandwidth" =~ ^[0-9]*\.[0-9]+$ ]]; then - local float_ok=$(awk -v val="$new_bandwidth" 'BEGIN { print (val >= 1 && val <= 40) ? "yes" : "no" }') - if [ "$float_ok" = "yes" ]; then - BANDWIDTH=$new_bandwidth - else - echo -e "${YELLOW}Invalid bandwidth. Keeping current: ${BANDWIDTH}${NC}" - fi - else - echo -e "${YELLOW}Invalid bandwidth. Keeping current: ${BANDWIDTH}${NC}" - fi - fi - - # Save settings - cat > $INSTALL_DIR/settings.conf << EOF -MAX_CLIENTS=$MAX_CLIENTS -BANDWIDTH=$BANDWIDTH -EOF - - echo "" - echo "Updating and recreating Conduit container with new settings..." - docker rm -f conduit 2>/dev/null || true - sleep 2 # Wait for container cleanup to complete - echo "Pulling latest image..." - docker pull $CONDUIT_IMAGE 2>/dev/null || echo -e "${YELLOW}Could not pull latest image, using cached version${NC}" - docker run -d \ - --name conduit \ - --restart unless-stopped \ - -v conduit-data:/home/conduit/data \ - --network host \ - $CONDUIT_IMAGE \ - start --max-clients "$MAX_CLIENTS" --bandwidth "$BANDWIDTH" -v - - if [ $? -eq 0 ]; then - echo -e "${GREEN}✓ Settings updated and Conduit restarted${NC}" - echo -e " Max Clients: ${MAX_CLIENTS}" - echo -e " Bandwidth: ${BANDWIDTH} Mbps" - else - echo -e "${RED}✗ Failed to restart Conduit${NC}" - fi -} - -show_logs() { - if ! docker ps -a 2>/dev/null | grep -q conduit; then - echo -e "${RED}Conduit container not found.${NC}" - return 1 - fi - # Filter out noisy 'context deadline exceeded' and 'port mapping: closed' errors - docker logs -f --tail 100 conduit 2>&1 | grep -vE "context deadline exceeded|port mapping: closed" -} - -uninstall_all() { - echo "" - echo -e "${RED}╔═══════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${RED}║ ⚠️ UNINSTALL CONDUIT ║${NC}" - echo -e "${RED}╚═══════════════════════════════════════════════════════════════════╝${NC}" - echo "" - echo "This will completely remove:" - echo " • Conduit Docker container" - echo " • Conduit Docker image" - echo " • Conduit data volume (all stored data)" - echo " • Auto-start service (systemd/OpenRC/SysVinit)" - echo " • Configuration files" - echo " • Management CLI" - echo "" - echo -e "${RED}WARNING: This action cannot be undone!${NC}" - echo "" - read -p "Are you sure you want to uninstall? (type 'yes' to confirm): " confirm < /dev/tty || true - - if [ "$confirm" != "yes" ]; then - echo "Uninstall cancelled." - return 0 - fi - - echo "" - echo "[INFO] Stopping Conduit container..." - docker stop conduit 2>/dev/null || true - - echo "[INFO] Removing Conduit container..." - docker rm -f conduit 2>/dev/null || true - - echo "[INFO] Removing Conduit Docker image..." - docker rmi $CONDUIT_IMAGE 2>/dev/null || true - - echo "[INFO] Removing Conduit data volume..." - docker volume rm conduit-data 2>/dev/null || true - - echo "[INFO] Removing auto-start service..." - # Systemd - systemctl stop conduit.service 2>/dev/null || true - systemctl disable conduit.service 2>/dev/null || true - rm -f /etc/systemd/system/conduit.service - systemctl daemon-reload 2>/dev/null || true - # OpenRC / SysVinit - rc-service conduit stop 2>/dev/null || true - rc-update del conduit 2>/dev/null || true - service conduit stop 2>/dev/null || true - update-rc.d conduit remove 2>/dev/null || true - chkconfig conduit off 2>/dev/null || true - rm -f /etc/init.d/conduit - - echo "[INFO] Removing configuration files..." - rm -rf /opt/conduit - rm -f /usr/local/bin/conduit - - echo "" - echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${GREEN}║ ✅ UNINSTALL COMPLETE! ║${NC}" - echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════════╝${NC}" - echo "" - echo "Conduit and all related components have been removed." - echo "" - echo "Note: Docker itself was NOT removed. To remove Docker:" - echo " apt-get purge docker-ce docker-ce-cli containerd.io" - echo "" -} - -show_menu() { - local redraw=true - while true; do - if [ "$redraw" = true ]; then - clear - print_header - - echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}" - echo -e "${CYAN} MANAGEMENT OPTIONS${NC}" - echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}" - echo -e " 1. 📈 View status dashboard (Live CPU/RAM)" - echo -e " 2. 📜 View traffic history (Scrolling Logs)" - echo -e " 3. 📋 View raw logs (Filtered)" - echo -e " 4. ⚙️ Change settings (max-clients, bandwidth)" - echo "" - echo -e " 5. ▶️ Start Conduit" - echo -e " 6. ⏹️ Stop Conduit" - echo -e " 7. 🔁 Restart Conduit" - echo "" - echo -e " u. 🗑️ Uninstall (remove everything)" - echo -e " 0. 🚪 Exit" - echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}" - echo "" - redraw=false - fi - - read -p " Enter choice: " choice < /dev/tty || { echo "Input error. Exiting."; exit 1; } - - case $choice in - 1) - show_dashboard - redraw=true - ;; - 2) - show_live_stats - read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true - redraw=true - ;; - 3) - show_logs - redraw=true - ;; - 4) - change_settings - redraw=true - ;; - 5) - start_conduit - read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true - redraw=true - ;; - 6) - stop_conduit - read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true - redraw=true - ;; - 7) - restart_conduit - read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true - redraw=true - ;; - u) - uninstall_all - exit 0 - ;; - 0) - echo "Exiting." - exit 0 - ;; - "") - # Ignore empty Enter key - ;; - *) - echo -e "${RED}Invalid choice: ${NC}${YELLOW}$choice${NC}" - echo -e "${CYAN}Choose an option from 0-7, or 'u' to uninstall.${NC}" - ;; - esac - done -} - -# Command line interface -show_help() { - echo "Usage: conduit [command]" - echo "" - echo "Commands:" - echo " status Show current status with resource usage" - echo " stats View live statistics" - echo " logs View raw Docker logs" - echo " start Start Conduit container" - echo " stop Stop Conduit container" - echo " restart Restart Conduit container" - echo " settings Change max-clients/bandwidth" - echo " uninstall Remove everything (container, data, service)" - echo " menu Open interactive menu (default)" - echo " help Show this help" -} - -case "${1:-menu}" in - status) show_status ;; - stats) show_live_stats ;; - logs) show_logs ;; - start) start_conduit ;; - stop) stop_conduit ;; - restart) restart_conduit ;; - settings) change_settings ;; - uninstall) uninstall_all ;; - help|-h|--help) show_help ;; - menu|*) show_menu ;; -esac -MANAGEMENT - - chmod +x $INSTALL_DIR/conduit - # Force create symlink (remove existing first) - rm -f /usr/local/bin/conduit 2>/dev/null || true - ln -s $INSTALL_DIR/conduit /usr/local/bin/conduit - - log_success "Management script installed: conduit" -} - -#═══════════════════════════════════════════════════════════════════════ -# Summary -#═══════════════════════════════════════════════════════════════════════ - -print_summary() { - # Determine which init system was used - local init_type="Enabled" - if [ "$HAS_SYSTEMD" = "true" ]; then - init_type="Enabled (systemd)" - elif command -v rc-update &>/dev/null; then - init_type="Enabled (OpenRC)" - elif [ -d /etc/init.d ]; then - init_type="Enabled (SysVinit)" - fi - - echo "" - echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${GREEN}║ ✅ INSTALLATION COMPLETE! ║${NC}" - echo -e "${GREEN}╠═══════════════════════════════════════════════════════════════════╣${NC}" - echo -e "${GREEN}║${NC} Conduit is running and ready to help users! ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} 📊 Settings: ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} Max Clients: ${CYAN}${MAX_CLIENTS}${NC} ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} Bandwidth: ${CYAN}${BANDWIDTH} Mbps${NC} ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} Auto-start: ${CYAN}${init_type}${NC} ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${GREEN}║${NC}" - echo -e "${GREEN}╠═══════════════════════════════════════════════════════════════════╣${NC}" - echo -e "${GREEN}║${NC} COMMANDS: ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit${NC} # Open management menu ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit stats${NC} # View live statistics + CPU/RAM ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit status${NC} # Quick status with resource usage ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit logs${NC} # View raw logs ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit settings${NC} # Change max-clients/bandwidth ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${CYAN}conduit uninstall${NC} # Remove everything ${GREEN}║${NC}" - echo -e "${GREEN}║${NC} ${GREEN}║${NC}" - echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════════╝${NC}" - echo "" - echo -e " ${YELLOW}View live stats now:${NC} conduit stats" - echo "" -} - -#═══════════════════════════════════════════════════════════════════════ -# Uninstall Function -#═══════════════════════════════════════════════════════════════════════ - -uninstall() { - echo -e "${CYAN}" - echo "╔═══════════════════════════════════════════════════════════════════╗" - echo "║ ⚠️ UNINSTALL CONDUIT ║" - echo "╚═══════════════════════════════════════════════════════════════════╝" - echo -e "${NC}" - echo "" - echo "This will completely remove:" - echo " • Conduit Docker container" - echo " • Conduit Docker image" - echo " • Conduit data volume (all stored data)" - echo " • Auto-start service (systemd/OpenRC/SysVinit)" - echo " • Configuration files" - echo " • Management CLI" - echo "" - echo -e "${RED}WARNING: This action cannot be undone!${NC}" - echo "" - read -p "Are you sure you want to uninstall? (type 'yes' to confirm): " confirm < /dev/tty || true - - if [ "$confirm" != "yes" ]; then - echo "Uninstall cancelled." - exit 0 - fi - - echo "" - log_info "Stopping Conduit container..." - docker stop conduit 2>/dev/null || true - - log_info "Removing Conduit container..." - docker rm -f conduit 2>/dev/null || true - - log_info "Removing Conduit Docker image..." - docker rmi ghcr.io/ssmirr/conduit/conduit:latest 2>/dev/null || true - - log_info "Removing Conduit data volume..." - docker volume rm conduit-data 2>/dev/null || true - - log_info "Removing auto-start service..." - # Systemd - systemctl stop conduit.service 2>/dev/null || true - systemctl disable conduit.service 2>/dev/null || true - rm -f /etc/systemd/system/conduit.service - systemctl daemon-reload 2>/dev/null || true - # OpenRC / SysVinit - rc-service conduit stop 2>/dev/null || true - rc-update del conduit 2>/dev/null || true - service conduit stop 2>/dev/null || true - update-rc.d conduit remove 2>/dev/null || true - chkconfig conduit off 2>/dev/null || true - rm -f /etc/init.d/conduit - - log_info "Removing configuration files..." - rm -rf /opt/conduit - rm -f /usr/local/bin/conduit - - echo "" - echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${GREEN}║ ✅ UNINSTALL COMPLETE! ║${NC}" - echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════════╝${NC}" - echo "" - echo "Conduit and all related components have been removed." - echo "" - echo "Note: Docker itself was NOT removed. To remove Docker:" - echo " apt-get purge docker-ce docker-ce-cli containerd.io" - echo "" -} - -#═══════════════════════════════════════════════════════════════════════ -# Main -#═══════════════════════════════════════════════════════════════════════ - -show_usage() { - echo "Psiphon Conduit Manager v${VERSION}" - echo "" - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Options:" - echo " (no args) Install or open management menu if already installed" - echo " --reinstall Force fresh reinstall" - echo " --uninstall Completely remove Conduit and all components" - echo " --help, -h Show this help message" - echo "" - echo "Examples:" - echo " sudo bash $0 # Install or open menu" - echo " sudo bash $0 --reinstall # Fresh install" - echo " sudo bash $0 --uninstall # Remove everything" - echo "" - echo "After install, use: conduit" -} - -main() { - # Handle command line arguments - case "${1:-}" in - --uninstall|-u) - check_root - uninstall - exit 0 - ;; - --help|-h) - show_usage - exit 0 - ;; - --reinstall) - # Force reinstall - FORCE_REINSTALL=true - ;; - esac - - print_header - check_root - detect_os - - # Check if already installed - if [ -f "$INSTALL_DIR/conduit" ] && [ "$FORCE_REINSTALL" != "true" ]; then - echo -e "${GREEN}Conduit is already installed!${NC}" - echo "" - echo "What would you like to do?" - echo "" - echo " 1. 📊 Open management menu" - echo " 2. 🔄 Reinstall (fresh install)" - echo " 3. 🗑️ Uninstall" - echo " 0. 🚪 Exit" - echo "" - read -p " Enter choice: " choice < /dev/tty || true - - case $choice in - 1) - echo -e "${CYAN}Opening management menu...${NC}" - create_management_script >/dev/null 2>&1 - exec /opt/conduit/conduit menu - ;; - 2) - echo "" - log_info "Starting fresh reinstall..." - # Continue with installation below - ;; - 3) - uninstall - exit 0 - ;; - 0) - echo "Exiting." - exit 0 - ;; - *) - echo -e "${RED}Invalid choice: ${NC}${YELLOW}$choice${NC}" - echo -e "${CYAN}Returning to installer...${NC}" - sleep 1 - main "$@" - ;; - esac - fi - - - check_dependencies - - # Interactive settings prompt - prompt_settings - - echo "" - echo -e "${CYAN}Starting installation...${NC}" - echo "" - - # Installation steps - log_info "Step 1/4: Installing Docker..." - install_docker - - echo "" - log_info "Step 2/4: Starting Conduit..." - run_conduit - - echo "" - log_info "Step 3/4: Setting up auto-start..." - save_settings - setup_autostart - - echo "" - log_info "Step 4/4: Creating management script..." - create_management_script - - print_summary - - # Ask if user wants to view live stats - read -p "View live statistics now? [Y/n] " view_stats < /dev/tty || true - if [[ ! "$view_stats" =~ ^[Nn] ]]; then - /opt/conduit/conduit stats - fi -} -# -# REACHED END OF SCRIPT - VERSION 1.0.0 -# ############################################################################### -main "$@"