#!/usr/bin/env bash # ZoPanel installer. # # curl -fsSL https://get.zopanel.net | sudo bash # curl -fsSL https://get.zopanel.net | sudo bash -s -- --php 8.3,8.2 --admin-email you@example.com # # Optional components (installed by the panel right after setup): # --profile full mail, webmail, DNS, WAF, Apache (.htaccess), FTP, PostgreSQL, Adminer, Docker # --with mail,webmail,dns,waf,apache,ftp,postgres,mongo,adminer,docker,storage # --mail-hostname mail.example.com needed for mail/webmail # --nameservers ns1.example.com,ns2.example.com needed for dns # Everything can also be installed later from Server → Components. # # The system is updated first (all packages, automatic security updates, # and on Ubuntu 22.04 the 6.8 HWE kernel); when a restart is needed the # installer asks once, at the start, and restarts at the end. # --yes ask nothing (defaults; no restart unless --reboot) # --reboot / --no-reboot # --kernel-backports Debian 12: install the 6.12 backports kernel # --keep-kernel never install a newer kernel # --no-os-upgrade leave the system packages as they are # --license KEY activate a license (or ZOPANEL_LICENSE_KEY=KEY) # Unattended (cloud-init, scripts): # curl -fsSL https://get.zopanel.net | sudo bash -s -- --yes --reboot # # The release manifest is verified with the ZoPanel Ed25519 release key and # the binary with the SHA-256 listed in that signed manifest. set -euo pipefail # Everything runs inside main() so a truncated download never executes. main() { BASE_URL="${ZOPANEL_URL:-https://update.zopanel.net}" CHANNEL="${ZOPANEL_CHANNEL:-stable}" RELEASE_PUBKEY="XitZpY6gmHkZfPC0eIgXnZSEP+tPpPa9fLeG8qffFPA=" INSTALL_DIR=/usr/local/zopanel/bin red() { printf '\033[31m%s\033[0m\n' "$*"; } info() { printf '\033[36m==>\033[0m %s\n' "$*"; } die() { red "Error: $*"; exit 1; } [ "$(id -u)" -eq 0 ] || die "please run as root (sudo)" [ -r /etc/os-release ] || die "cannot detect the operating system" . /etc/os-release case "${ID}:${VERSION_ID}" in ubuntu:22.04|ubuntu:24.04|debian:12|debian:13) ;; *) [ "${ZOPANEL_FORCE:-0}" = "1" ] || die "unsupported OS ${PRETTY_NAME} (Ubuntu 22.04/24.04, Debian 12/13). Set ZOPANEL_FORCE=1 to try anyway." ;; esac case "$(uname -m)" in x86_64) ARCH=amd64 ;; aarch64|arm64) ARCH=arm64 ;; *) die "unsupported architecture $(uname -m)" ;; esac if ! command -v curl >/dev/null || ! command -v openssl >/dev/null; then info "Installing curl and openssl" apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq curl ca-certificates openssl >/dev/null fi TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT mkdir -p "$INSTALL_DIR" if [ -n "${ZOPANEL_BINARY:-}" ]; then info "Using local binary ${ZOPANEL_BINARY}" install -m 0755 "$ZOPANEL_BINARY" "$INSTALL_DIR/zopanel" else info "Downloading release manifest (${CHANNEL})" curl --proto =https --tlsv1.2 -fsSL "${BASE_URL}/${CHANNEL}/manifest.json" -o "$TMP/manifest.json" curl --proto =https --tlsv1.2 -fsSL "${BASE_URL}/${CHANNEL}/manifest.json.sig" -o "$TMP/manifest.json.sig" # Ed25519 public key: wrap the raw 32 bytes into a SubjectPublicKeyInfo. { printf '\x30\x2a\x30\x05\x06\x03\x2b\x65\x70\x03\x21\x00'; printf '%s' "$RELEASE_PUBKEY" | base64 -d; } > "$TMP/pub.der" openssl pkey -pubin -inform DER -in "$TMP/pub.der" -out "$TMP/pub.pem" 2>/dev/null || die "openssl cannot read the release key" base64 -d "$TMP/manifest.json.sig" > "$TMP/sig.bin" openssl pkeyutl -verify -pubin -inkey "$TMP/pub.pem" -rawin -in "$TMP/manifest.json" -sigfile "$TMP/sig.bin" >/dev/null 2>&1 \ || die "release manifest signature is INVALID — aborting" info "Manifest signature verified" ASSET="linux-${ARCH}" # Extract url/sha256 for our platform without needing jq. BLOCK="$(tr -d '\n ' < "$TMP/manifest.json" | grep -o "\"${ASSET}\":{[^}]*}")" || die "no build for ${ASSET}" URL="$(printf '%s' "$BLOCK" | sed -E 's/.*"url":"([^"]+)".*/\1/')" SUM="$(printf '%s' "$BLOCK" | sed -E 's/.*"sha256":"([0-9a-fA-F]+)".*/\1/')" VERSION="$(tr -d '\n ' < "$TMP/manifest.json" | sed -E 's/.*"version":"([^"]+)".*/\1/')" case "$URL" in https://*) ;; *) die "release URL must use https" ;; esac info "Downloading ZoPanel ${VERSION} (${ARCH})" curl --proto =https --tlsv1.2 -fSL --progress-bar "$URL" -o "$TMP/zopanel" echo "${SUM} $TMP/zopanel" | sha256sum -c --quiet - || die "checksum mismatch" install -m 0755 "$TMP/zopanel" "$INSTALL_DIR/zopanel" fi ln -sf "$INSTALL_DIR/zopanel" /usr/local/bin/zopanel exec "$INSTALL_DIR/zopanel" setup "$@" } main "$@"