diff --git a/ct/unifi-os-server.sh b/ct/unifi-os-server.sh new file mode 100644 index 000000000..a6da9d366 --- /dev/null +++ b/ct/unifi-os-server.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func) +# Copyright (c) 2021-2026 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# Source: https://ui.com/ + +APP="UniFi OS Server" +var_tags="${var_tags:-network}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-20}" +var_os="${var_os:-debian}" +var_version="${var_version:-12}" +var_unprivileged="${var_unprivileged:-0}" +var_tun="${var_tun:-yes}" +var_nesting="${var_nesting:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -f /usr/local/sbin/unifi-os-server.bin && ! -d /data/unifi ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_error "UniFi OS Server updates are handled by the UniFi OS app itself." + exit +} + +start +build_container +description + +msg_ok "Completed successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" diff --git a/install/unifi-os-server-install.sh b/install/unifi-os-server-install.sh new file mode 100644 index 000000000..58dea42cf --- /dev/null +++ b/install/unifi-os-server-install.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE +# Source: https://ui.com/ + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +if [[ "${CTTYPE:-1}" != "0" ]]; then + msg_error "UniFi OS Server requires a privileged LXC container." + msg_error "Recreate the container with unprivileged=0." + exit 1 +fi + +if [[ ! -e /dev/net/tun ]]; then + msg_error "Missing /dev/net/tun in container." + msg_error "Enable TUN/TAP (var_tun=yes) or add /dev/net/tun passthrough." + exit 1 +fi + +msg_info "Installing dependencies" +$STD apt-get install -y ca-certificates curl jq podman uidmap slirp4netns wget +msg_ok "Installed dependencies" + +msg_info "Installing sysctl wrapper (ignore non-critical errors)" +cat <<'EOF' >/usr/local/sbin/sysctl +#!/bin/sh +/usr/sbin/sysctl "$@" || true +exit 0 +EOF +chmod +x /usr/local/sbin/sysctl +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +msg_ok "Sysctl wrapper installed" + +msg_info "Fetching latest UniFi OS Server" +API_URL="https://fw-update.ui.com/api/firmware-latest" +TEMP_JSON="$(mktemp)" +if ! curl -fsSL "$API_URL" -o "$TEMP_JSON"; then + rm -f "$TEMP_JSON" + msg_error "Failed to fetch data from Ubiquiti API" + exit 1 +fi + +LATEST=$(jq -r ' + ._embedded.firmware + | map(select(.product == "unifi-os-server")) + | map(select(.platform == "linux-x64")) + | sort_by(.version_major, .version_minor, .version_patch) + | last +' "$TEMP_JSON") + +UOS_VERSION=$(echo "$LATEST" | jq -r '.version' | sed 's/^v//') +UOS_URL=$(echo "$LATEST" | jq -r '._links.data.href') +rm -f "$TEMP_JSON" + +if [[ -z "$UOS_URL" || -z "$UOS_VERSION" || "$UOS_URL" == "null" ]]; then + msg_error "Failed to parse UniFi OS Server version or download URL" + exit 1 +fi +msg_ok "Found UniFi OS Server ${UOS_VERSION}" + +msg_info "Downloading UniFi OS Server installer" +mkdir -p /usr/local/sbin +curl -fsSL "$UOS_URL" -o /usr/local/sbin/unifi-os-server.bin +chmod +x /usr/local/sbin/unifi-os-server.bin +msg_ok "Downloaded UniFi OS Server installer" + +msg_info "Installing UniFi OS Server (this takes a few minutes)" +echo y | /usr/local/sbin/unifi-os-server.bin +msg_ok "UniFi OS Server installed" + +motd_ssh +customize +cleanup_lxc diff --git a/misc/alpine-tools.func b/misc/alpine-tools.func index 5a1043b94..955554216 100644 --- a/misc/alpine-tools.func +++ b/misc/alpine-tools.func @@ -3,6 +3,20 @@ # Erwartet vorhandene msg_* und optional $STD aus deinem Framework. +# Fallbacks, wenn core.func nicht geladen wurde (Alpine/ash-safe) +if ! command -v msg_info >/dev/null 2>&1; then + msg_info() { echo "[INFO] $*"; } +fi +if ! command -v msg_ok >/dev/null 2>&1; then + msg_ok() { echo "[OK] $*"; } +fi +if ! command -v msg_warn >/dev/null 2>&1; then + msg_warn() { echo "[WARN] $*"; } +fi +if ! command -v msg_error >/dev/null 2>&1; then + msg_error() { echo "[ERROR] $*" >&2; } +fi + # ------------------------------ # helpers # ------------------------------