diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..edc445e --- /dev/null +++ b/install.sh @@ -0,0 +1,464 @@ +#!/bin/bash + +# WireGuard Server Setup with Gluetun (Docker) +# Author: Assistant +# Date: $(date +%Y-%m-%d) + +set -e + +# Colors for better readability +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Logging functions +log() { + echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" >&2 +} + +success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +# Check root privileges +check_root() { + if [[ $EUID -ne 0 ]]; then + error "This script must be run as root!" + exit 1 + fi +} + +# Check operating system +check_os() { + if [[ ! -f /etc/debian_version ]]; then + error "This script is designed for Debian systems!" + exit 1 + fi + success "Debian system detected" +} + +# Check package availability +check_packages() { + log "Checking installed packages..." + + local required_packages=("curl" "wget" "apt-transport-https" "ca-certificates" "gnupg" "lsb-release" "net-tools" "iptables") + local missing_packages=() + + for package in "${required_packages[@]}"; do + if ! dpkg -l | grep -q "^ii $package "; then + missing_packages+=("$package") + else + success "$package is already installed" + fi + done + + # Check Docker + if ! command -v docker &> /dev/null; then + missing_packages+=("docker") + warning "Docker is not installed" + else + success "Docker is already installed" + fi + + if ! command -v docker-compose &> /dev/null; then + missing_packages+=("docker-compose") + warning "Docker Compose is not installed" + else + success "Docker Compose is already installed" + fi + + if [[ ${#missing_packages[@]} -gt 0 ]]; then + warning "The following packages need to be installed: ${missing_packages[*]}" + return 1 + else + success "All required packages are already installed" + return 0 + fi +} + +# Update system +update_system() { + log "Updating package list..." + apt update -q + + log "Performing system upgrade..." + apt upgrade -y -q + + success "System has been updated" +} + +# Install basic packages +install_basic_packages() { + log "Installing basic packages..." + + local packages=("curl" "wget" "apt-transport-https" "ca-certificates" "gnupg" "lsb-release" "net-tools" "iptables" "ufw" "nano") + + apt install -y "${packages[@]}" + success "Basic packages installed" +} + +# Install Docker +install_docker() { + if command -v docker &> /dev/null; then + success "Docker is already installed" + return 0 + fi + + log "Installing Docker..." + + # Remove old Docker versions + apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true + + # Add Docker GPG key + curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + + # Add Docker repository + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + + # Update package list + apt update -q + + # Install Docker + apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + + # Start and enable Docker + systemctl enable docker + systemctl start docker + + success "Docker has been installed and started" +} + +# Install Docker Compose +install_docker_compose() { + if command -v docker-compose &> /dev/null; then + success "Docker Compose is already installed" + return 0 + fi + + log "Installing Docker Compose..." + + # Get latest version + local compose_version=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4) + + # Download Docker Compose + curl -L "https://github.com/docker/compose/releases/download/${compose_version}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + + # Make executable + chmod +x /usr/local/bin/docker-compose + + # Create symlink + ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose + + success "Docker Compose has been installed" +} + +# Configure static IP +configure_static_ip() { + log "Configuring static IP..." + + # Show available network interfaces + echo -e "\n${YELLOW}Available network interfaces:${NC}" + ip link show | grep -E "^[0-9]+: " | cut -d: -f2 | tr -d ' ' + + echo -e "\n${YELLOW}Current IP configuration:${NC}" + ip addr show | grep -E "inet [0-9]" | grep -v 127.0.0.1 + + echo -e "\n" + read -p "Would you like to configure a static IP? (y/n): " configure_ip + + if [[ $configure_ip =~ ^[Yy]$ ]]; then + read -p "Interface (e.g. eth0, ens18): " interface + read -p "Static IP address (e.g. 192.168.1.100/24): " static_ip + read -p "Gateway (e.g. 192.168.1.1): " gateway + read -p "DNS server (e.g. 8.8.8.8): " dns_server + + # Backup current configuration + cp /etc/network/interfaces /etc/network/interfaces.backup.$(date +%s) + + # Create new configuration + cat > /etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +source /etc/network/interfaces.d/* + +# The loopback network interface +auto lo +iface lo inet loopback + +# Static IP configuration +auto $interface +iface $interface inet static + address $static_ip + gateway $gateway + dns-nameservers $dns_server +EOF + + success "Static IP configuration created" + warning "Network will be restarted after script completion" + else + log "Static IP configuration skipped" + fi +} + +# Get WireGuard configuration +get_wireguard_config() { + log "Getting WireGuard configuration..." + + echo -e "\n${YELLOW}Please enter your WireGuard configuration data:${NC}" + + read -p "WireGuard Private Key: " WG_PRIVATE_KEY + read -p "WireGuard Public Key: " WG_PUBLIC_KEY + read -p "WireGuard Preshared Key (optional, Enter for empty): " WG_PRESHARED_KEY + read -p "WireGuard Endpoint (e.g. vpn.example.com:51820): " WG_ENDPOINT + read -p "WireGuard Allowed IPs (e.g. 0.0.0.0/0): " WG_ALLOWED_IPS + read -p "WireGuard Interface IP - IPv4 only (e.g. 10.0.0.2/32): " WG_INTERFACE_IP + + # Remove IPv6 addresses from input (Gluetun compatibility) + WG_INTERFACE_IP=$(echo "$WG_INTERFACE_IP" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+' | head -1) + + if [[ -z "$WG_INTERFACE_IP" ]]; then + warning "No valid IPv4 address detected. Please use IPv4 only (e.g. 10.0.0.2/32)" + read -p "WireGuard Interface IP (IPv4 only): " WG_INTERFACE_IP + fi + + # Validation + if [[ -z "$WG_PRIVATE_KEY" ]] || [[ -z "$WG_PUBLIC_KEY" ]] || [[ -z "$WG_ENDPOINT" ]]; then + error "Private Key, Public Key and Endpoint are required!" + exit 1 + fi + + success "WireGuard configuration captured" +} + +# Setup Gluetun directory and configuration +setup_gluetun() { + log "Creating Gluetun configuration..." + + # Create working directory + mkdir -p /opt/gluetun + cd /opt/gluetun + + # Create Docker Compose file + cat > docker-compose.yml << EOF +services: + gluetun: + image: qmcgaw/gluetun:latest + container_name: gluetun-wireguard + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - "8888:8888/tcp" # HTTP proxy + - "8388:8388/tcp" # Shadowsocks + - "8388:8388/udp" # Shadowsocks + environment: + - VPN_SERVICE_PROVIDER=custom + - VPN_TYPE=wireguard + - WIREGUARD_ENDPOINT_IP=${WG_ENDPOINT%:*} + - WIREGUARD_ENDPOINT_PORT=${WG_ENDPOINT#*:} + - WIREGUARD_PRIVATE_KEY=${WG_PRIVATE_KEY} + - WIREGUARD_PUBLIC_KEY=${WG_PUBLIC_KEY} + - WIREGUARD_ADDRESSES=${WG_INTERFACE_IP} + - WIREGUARD_ALLOWED_IPS=${WG_ALLOWED_IPS:-0.0.0.0/0} + - HTTPPROXY=on + - HTTPPROXY_LOG=on + - HTTPPROXY_LISTENING_ADDRESS=:8888 + - SHADOWSOCKS=on + - SHADOWSOCKS_LOG=on + - SHADOWSOCKS_LISTENING_ADDRESS=:8388 + - LOG_LEVEL=info + - HEALTH_VPN_DURATION_INITIAL=10s + - HEALTH_VPN_DURATION_ADDITION=5s + - DOT=off + - FIREWALL_OUTBOUND_SUBNETS=192.168.0.0/16,172.16.0.0/12,10.0.0.0/8 +EOF + + # Add preshared key if provided + if [[ -n "$WG_PRESHARED_KEY" ]]; then + echo " - WIREGUARD_PRESHARED_KEY=${WG_PRESHARED_KEY}" >> docker-compose.yml + fi + + success "Gluetun Docker Compose file created" +} + +# Configure firewall +configure_firewall() { + log "Configuring UFW firewall..." + + # Reset and enable UFW + ufw --force reset + ufw --force enable + + # Default rules + ufw default deny incoming + ufw default allow outgoing + + # Allow SSH + ufw allow ssh + + # Allow proxy ports + ufw allow 8888/tcp comment "Gluetun HTTP Proxy" + ufw allow 8388 comment "Gluetun SOCKS Proxy" + + # Allow Docker subnets + ufw allow from 172.17.0.0/16 + ufw allow from 172.18.0.0/16 + + success "Firewall configured" +} + +# Start Gluetun +start_gluetun() { + log "Starting Gluetun container..." + + cd /opt/gluetun + + # Stop container if already running + docker-compose down 2>/dev/null || true + + # Update images + docker-compose pull + + # Start container + docker-compose up -d + + success "Gluetun container started" +} + +# Check status +check_status() { + log "Checking container status..." + + sleep 5 + + if docker ps | grep -q gluetun-wireguard; then + success "Gluetun container is running" + + # Show logs + echo -e "\n${YELLOW}Container logs (last 20 lines):${NC}" + docker logs --tail 20 gluetun-wireguard + + # Check VPN status + echo -e "\n${YELLOW}Checking VPN status...${NC}" + sleep 10 + + # Check IP address via VPN + local vpn_ip=$(docker exec gluetun-wireguard wget -qO- https://ipinfo.io/ip 2>/dev/null || echo "Error retrieving IP") + echo -e "${GREEN}VPN IP address: ${vpn_ip}${NC}" + + else + error "Gluetun container is not running!" + echo -e "\n${RED}Container logs:${NC}" + docker logs gluetun-wireguard 2>/dev/null || echo "No logs available" + fi +} + +# Create systemd service +create_systemd_service() { + log "Creating systemd service..." + + cat > /etc/systemd/system/gluetun.service << EOF +[Unit] +Description=Gluetun VPN Container +Requires=docker.service +After=docker.service + +[Service] +Type=oneshot +RemainAfterExit=yes +WorkingDirectory=/opt/gluetun +ExecStart=/usr/local/bin/docker-compose up -d +ExecStop=/usr/local/bin/docker-compose down +TimeoutStartSec=0 + +[Install] +WantedBy=multi-user.target +EOF + + systemctl daemon-reload + systemctl enable gluetun.service + + success "Systemd service created and enabled" +} + +# Show summary +show_summary() { + echo -e "\n${GREEN}===========================================${NC}" + echo -e "${GREEN} Installation completed successfully!${NC}" + echo -e "${GREEN}===========================================${NC}" + + echo -e "\n${YELLOW}Proxy Settings:${NC}" + echo -e "HTTP/HTTPS Proxy: http://$(hostname -I | awk '{print $1}'):8888" + echo -e "SOCKS5 Proxy: $(hostname -I | awk '{print $1}'):8388" + + echo -e "\n${YELLOW}Useful Commands:${NC}" + echo -e "Container status: ${BLUE}docker ps${NC}" + echo -e "Container logs: ${BLUE}docker logs gluetun-wireguard${NC}" + echo -e "Stop container: ${BLUE}systemctl stop gluetun${NC}" + echo -e "Start container: ${BLUE}systemctl start gluetun${NC}" + echo -e "Restart container: ${BLUE}systemctl restart gluetun${NC}" + + echo -e "\n${YELLOW}Configuration Files:${NC}" + echo -e "Docker Compose: ${BLUE}/opt/gluetun/docker-compose.yml${NC}" + echo -e "Systemd Service: ${BLUE}/etc/systemd/system/gluetun.service${NC}" + + if [[ $configure_ip =~ ^[Yy]$ ]]; then + echo -e "\n${YELLOW}Important:${NC} System must be rebooted to activate static IP!" + read -p "Would you like to reboot the system now? (y/n): " reboot_now + if [[ $reboot_now =~ ^[Yy]$ ]]; then + log "Rebooting system..." + reboot + fi + fi +} + +# Main function +main() { + echo -e "${BLUE}" + echo "==============================================" + echo " WireGuard Server Setup with Gluetun (Docker)" + echo "==============================================" + echo -e "${NC}\n" + + # Validations + check_root + check_os + + # System setup + if ! check_packages; then + update_system + install_basic_packages + install_docker + install_docker_compose + fi + + # Network configuration + configure_static_ip + + # WireGuard setup + get_wireguard_config + setup_gluetun + configure_firewall + create_systemd_service + start_gluetun + + # Status and summary + check_status + show_summary +} + +# Execute script +main "$@" \ No newline at end of file