#!/usr/bin/env bash set -euo pipefail ######################################## # Seby's Calagopus Wings Installer # curl | bash safe ######################################## ######################################## # Styling ######################################## TTY="/dev/tty" BOLD="\033[1m" DIM="\033[2m" GREEN="\033[32m" YELLOW="\033[33m" RED="\033[31m" BLUE="\033[34m" RESET="\033[0m" section() { printf "\n${BLUE}${BOLD}==> %s${RESET}\n" "$*"; } say() { printf "${GREEN}✔ %s${RESET}\n" "$*"; } warn() { printf "${YELLOW}⚠ %s${RESET}\n" "$*"; } err() { printf "${RED}✖ %s${RESET}\n" "$*"; } have() { command -v "$1" >/dev/null 2>&1; } need_tty() { if [[ ! -r "$TTY" || ! -w "$TTY" ]]; then err "No interactive TTY available." exit 1 fi } prompt() { local msg="$1" local out printf "${BOLD}%s${RESET}" "$msg" >"$TTY" IFS= read -r out <"$TTY" printf "%s" "$out" } confirm_default_no() { local msg="$1" local ans ans="$(prompt "$msg [y/N]: ")" [[ "${ans,,}" == "y" || "${ans,,}" == "yes" ]] } require_root_or_sudo() { if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then if have sudo; then SUDO="sudo" else err "Root or sudo required." exit 1 fi else SUDO="" fi } apt_install() { $SUDO apt-get update -y >/dev/null 2>&1 $SUDO apt-get install -y "$@" >/dev/null 2>&1 } ######################################## # SSL config updater ######################################## update_ssl_config() { local domain="$1" local cfg="/etc/pterodactyl/config.yml" local cert="/etc/letsencrypt/live/${domain}/fullchain.pem" local key="/etc/letsencrypt/live/${domain}/privkey.pem" if [[ ! -f "$cfg" ]]; then warn "Config not found — skipping SSL update." return fi if [[ ! -f "$cert" || ! -f "$key" ]]; then warn "Cert files not found — skipping SSL update." return fi section "Updating SSL configuration" $SUDO cp -a "$cfg" "${cfg}.bak" $SUDO awk -v cert="$cert" -v key="$key" ' BEGIN { inssl=0 } { if ($0 ~ /^ ssl:[[:space:]]*$/) { inssl=1; print; next } if (inssl==1) { if ($0 ~ /^ [^[:space:]]/ && $0 !~ /^ ssl:/) { inssl=0 } else if ($0 ~ /^ enabled:/) { print " enabled: true"; next } else if ($0 ~ /^ cert:/) { print " cert: " cert; next } else if ($0 ~ /^ key:/) { print " key: " key; next } } print } ' "$cfg" | $SUDO tee "$cfg" >/dev/null say "SSL block updated (backup saved)" } ######################################## # Header ######################################## clear cat << "EOF" ____ _ / ___|__ _| | __ _ __ _ ___ _ __ _ _ ___ | | / _` | |/ _` |/ _` |/ _ \| '_ \| | | / __| | |__| (_| | | (_| | (_| | (_) | |_) | |_| \__ \ \____\__,_|_|\__,_|\__, |\___/| .__/ \__,_|___/ |___/ |_| Calagopus Wings Installer | v1.0 EOF need_tty require_root_or_sudo if ! have apt-get; then err "Only Debian/Ubuntu supported." exit 1 fi ######################################## # Docker ######################################## section "Docker Check" if have docker; then say "Docker detected: $(docker --version || true)" else warn "Docker not installed." if confirm_default_no "Install Docker?"; then section "Installing Docker (quiet mode)" apt_install ca-certificates curl if curl -fsSL https://get.docker.com/ | CHANNEL=stable $SUDO bash >/dev/null 2>&1; then say "Docker installed successfully" say "$(docker --version)" else err "Docker installation failed" exit 1 fi else err "Docker required. Exiting." exit 1 fi fi ######################################## # Download Wings ######################################## section "Downloading Wings" ARCH="$(uname -m)" case "$ARCH" in x86_64|amd64) WINGS_ARCH="x86_64" ;; aarch64|arm64) WINGS_ARCH="aarch64" ;; *) err "Unsupported architecture: $ARCH" exit 1 ;; esac WINGS_URL="https://github.com/calagopus/wings/releases/latest/download/wings-rs-${WINGS_ARCH}-linux" WINGS_BIN="/usr/local/bin/wings" $SUDO curl -fL "$WINGS_URL" -o "$WINGS_BIN" >/dev/null 2>&1 $SUDO chmod +x "$WINGS_BIN" say "Wings installed" "$WINGS_BIN" version || true ######################################## # Configure ######################################## CONFIG_CREATED=false section "Configuration" if confirm_default_no "Run wings configure --join-data now?"; then JOIN_DATA="$(prompt "Paste join-data string: ")" if [[ -n "$JOIN_DATA" ]]; then $SUDO mkdir -p /etc/pterodactyl $SUDO "$WINGS_BIN" configure --join-data "$JOIN_DATA" CONFIG_CREATED=true say "Configuration complete" else warn "No join-data provided" fi fi ######################################## # SSL ######################################## if $CONFIG_CREATED && confirm_default_no "Set up SSL with certbot?"; then section "SSL Setup" DOMAIN="$(prompt "Enter domain: ")" EMAIL="$(prompt "Enter email: ")" if [[ -n "$DOMAIN" && -n "$EMAIL" ]]; then apt_install certbot $SUDO certbot certonly \ --standalone \ -d "$DOMAIN" \ --non-interactive \ --agree-tos \ --email "$EMAIL" \ --no-eff-email update_ssl_config "$DOMAIN" else warn "Domain/email missing — skipping SSL" fi fi ######################################## # Service ######################################## section "Service Installation" if confirm_default_no "Install as systemd service?"; then $SUDO "$WINGS_BIN" service-install say "Service installed" $SUDO systemctl --no-pager status wings || true fi section "Done" say "Calagopus Wings installation complete."