#!/usr/bin/env bash set -euo pipefail # Constants DOMAIN="" EMAIL="" HY_PASS="" NO_UFW=0 NO_SYSCTL=0 # Colors GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # No Color log() { echo -e "${GREEN}[+] $*${NC}"; } warn() { echo -e "${YELLOW}[!] $*${NC}" >&2; } err() { echo -e "${RED}[✗] $*${NC}" >&2; exit 1; } need_root() { [[ "${EUID}" -eq 0 ]] || err "Please run as root: sudo bash $0 ..." } check_os() { if [[ -f /etc/os-release ]]; then source /etc/os-release if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then warn "This script is optimized for Debian/Ubuntu. Your OS (${ID}) might not be supported." read -r -p "Press ENTER to continue anyway, or Ctrl+C to abort..." fi else err "Cannot detect OS. /etc/os-release not found." fi } has_cmd() { command -v "$1" >/dev/null 2>&1; } usage() { cat < -e [-p ] [--no-ufw] [--no-sysctl] Options: -d, --domain Domain name (required) -e, --email Email for Let's Encrypt registration (required) -p, --password HY password (optional; auto-generated if omitted) --no-ufw Do not enable/modify UFW (firewall) --no-sysctl Do not apply sysctl tuning (UDP buffers) -h, --help Show this help message Example: sudo bash $0 -d example.com -e admin@example.com EOF } parse_args() { while [[ $# -gt 0 ]]; do case "$1" in -d|--domain) DOMAIN="${2:-}"; shift 2;; -e|--email) EMAIL="${2:-}"; shift 2;; -p|--password) HY_PASS="${2:-}"; shift 2;; --no-ufw) NO_UFW=1; shift 1;; --no-sysctl) NO_SYSCTL=1; shift 1;; -h|--help) usage; exit 0;; *) err "Unknown argument: $1 (use -h for help)";; esac done # Interactive prompts if missing args if [[ -z "${DOMAIN}" ]]; then read -r -p "Enter your domain (e.g., example.com): " DOMAIN fi if [[ -z "${EMAIL}" ]]; then read -r -p "Enter your email for Let's Encrypt: " EMAIL fi # Generate password if missing if [[ -z "${HY_PASS}" ]]; then if has_cmd openssl; then HY_PASS="$(openssl rand -base64 24 | tr -d '\n')" else HY_PASS="$(tr -dc 'A-Za-z0-9' "${webroot}/index.html" < Welcome to ${DOMAIN}

${DOMAIN}

Site is under construction.

EOF chown -R www-data:www-data "${webroot}" local site_avail="/etc/nginx/sites-available/${DOMAIN}" if [[ -f "${site_avail}" ]]; then cp -a "${site_avail}" "${site_avail}.$(date +%F_%H%M%S).bak" warn "Existing nginx config found. Backed up to ${site_avail}.bak" fi cat > "${site_avail}" < /etc/hysteria/config.yaml < /etc/sysctl.d/99-hy.conf <<'EOF' net.core.rmem_max=16777216 net.core.wmem_max=16777216 EOF sysctl --system >/dev/null } setup_ufw() { [[ "${NO_UFW}" -eq 1 ]] && { warn "Skipping UFW setup."; return 0; } log "Configuring UFW firewall..." ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS ufw allow 443/udp # HY (QUIC) if ufw status | grep -qi "inactive"; then echo "y" | ufw enable >/dev/null || true fi } print_proxies() { echo echo "========== Client Config Snippet ==========" cat <