diff --git a/ct/rustypaste.sh b/ct/rustypaste.sh index 504e142dd..a4f1bb6da 100644 --- a/ct/rustypaste.sh +++ b/ct/rustypaste.sh @@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/ APP="rustypaste" var_tags="${var_tags:-pastebin;storage}" var_cpu="${var_cpu:-1}" -var_ram="${var_ram:-512}" +var_ram="${var_ram:-1024}" var_disk="${var_disk:-20}" var_os="${var_os:-debian}" var_version="${var_version:-13}" @@ -20,38 +20,38 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -f "/opt/rustypaste/target/release/rustypaste" ]]; then - msg_error "No rustypaste Installation Found!" - exit - fi - - if check_for_gh_release "rustypaste" "orhun/rustypaste"; then - msg_info "Stopping Services" - systemctl stop rustypaste - msg_ok "Stopped Services" - - msg_info "Creating Backup" - tar -czf "/opt/rustypaste_backup_$(date +%F).tar.gz" "/opt/rustypaste/upload" - msg_ok "Backup Created" - - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "tarball" "latest" "/opt/rustypaste" - - msg_info "Updating rustypaste" - cd /opt/rustypaste - sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml - $STD cargo build --locked --release - msg_ok "Updated rustypaste" - - msg_info "Starting Services" - systemctl start rustypaste - msg_ok "Started Services" - msg_ok "Updated successfully!" - fi + if [[ ! -f "/opt/rustypaste/target/release/rustypaste" ]]; then + msg_error "No rustypaste Installation Found!" exit + fi + + if check_for_gh_release "rustypaste" "orhun/rustypaste"; then + msg_info "Stopping Services" + systemctl stop rustypaste + msg_ok "Stopped Services" + + msg_info "Creating Backup" + tar -czf "/opt/rustypaste_backup_$(date +%F).tar.gz" "/opt/rustypaste/upload" + msg_ok "Backup Created" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "tarball" "latest" "/opt/rustypaste" + + msg_info "Updating rustypaste" + cd /opt/rustypaste + sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml + $STD cargo build --locked --release + msg_ok "Updated rustypaste" + + msg_info "Starting Services" + systemctl start rustypaste + msg_ok "Started Services" + msg_ok "Updated successfully!" + fi + exit } start diff --git a/frontend/public/json/rustypaste.json b/frontend/public/json/rustypaste.json index ac81889d5..e71f72687 100644 --- a/frontend/public/json/rustypaste.json +++ b/frontend/public/json/rustypaste.json @@ -20,7 +20,7 @@ "script": "ct/rustypaste.sh", "resources": { "cpu": 1, - "ram": 512, + "ram": 1024, "hdd": 20, "os": "Debian", "version": "13" @@ -32,9 +32,9 @@ "password": null }, "notes": [ - { - "text": "When updating the script it will backup the whole project including all the uploaded files, make sure to extract it to a safe location or remove", - "type": "info" - } + { + "text": "When updating the script it will backup the whole project including all the uploaded files, make sure to extract it to a safe location or remove", + "type": "info" + } ] } diff --git a/install/alpine-rustypaste-install.sh b/install/alpine-rustypaste-install.sh new file mode 100644 index 000000000..ddc9ec9cf --- /dev/null +++ b/install/alpine-rustypaste-install.sh @@ -0,0 +1,46 @@ +#!/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://github.com/orhun/rustypaste + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "prebuild" "latest" "/opt/rustypaste" "*x86_64-unknown-linux-musl.tar.gz" + +msg_info "Setting up rustypaste" +cd /opt/rustypaste +sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml +msg_ok "Set up rustypaste" + +msg_info "Creating Service" +cat <<'EOF' >/etc/init.d/rustypaste +#!/sbin/openrc-run + +name="rustypaste" +description="rustypaste Service" +directory="/opt/rustypaste" +command="/opt/rustypaste/rustypaste" +command_args="" +pidfile="/run/${RC_SVCNAME}.pid" +command_background="yes" +start_stop_daemon_args="--user root" + +depend() { + need net +} +EOF +chmod +x /etc/init.d/rustypaste +rc-update add rustypaste default +rc-service rustypaste start +msg_ok "Created Service" + +motd_ssh +customize diff --git a/install/rustypaste-install.sh b/install/rustypaste-install.sh index 1777780c0..abb0b88ff 100644 --- a/install/rustypaste-install.sh +++ b/install/rustypaste-install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Copyright (c) 2021-2026 community-scripts ORG -# Author: GoldenSpringness +# Author: GoldenSpringness | MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE # Source: https://github.com/orhun/rustypaste @@ -13,17 +13,11 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies" -$STD apt install -y build-essential -msg_ok "Dependencies Installed Successfully" - -RUST_VERSION="1.92.0" setup_rust -fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "tarball" +fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "prebuild" "latest" "/opt/rustypaste" "*x86_64-unknown-linux-gnu.tar.gz" msg_info "Setting up rustypaste" cd /opt/rustypaste sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml -$STD cargo build --locked --release msg_ok "Set up rustypaste" msg_info "Creating Service" @@ -34,7 +28,7 @@ After=network.target [Service] WorkingDirectory=/opt/rustypaste -ExecStart=/opt/rustypaste/target/release/rustypaste +ExecStart=/opt/rustypaste/rustypaste Restart=always [Install] diff --git a/misc/alpine-tools.func b/misc/alpine-tools.func index 663b5f1d3..5a1043b94 100644 --- a/misc/alpine-tools.func +++ b/misc/alpine-tools.func @@ -9,6 +9,145 @@ lower() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; } has() { command -v "$1" >/dev/null 2>&1; } +# tools.func compatibility helpers (Alpine-safe) +cache_installed_version() { + local app="$1" version="$2" + mkdir -p /var/cache/app-versions + echo "$version" >"/var/cache/app-versions/${app}_version.txt" +} + +get_cached_version() { + local app="$1" + mkdir -p /var/cache/app-versions + if [ -f "/var/cache/app-versions/${app}_version.txt" ]; then + cat "/var/cache/app-versions/${app}_version.txt" + return 0 + fi + return 0 +} + +version_gt() { + # returns 0 if $1 > $2 + # BusyBox-safe version compare + awk -v a="$1" -v b="$2" ' + function splitver(v, arr) { n=split(v, arr, /\./); return n } + BEGIN { + na=splitver(a, A); nb=splitver(b, B); + n=(na>nb?na:nb); + for (i=1;i<=n;i++) { + va=(A[i]==""?0:A[i]); vb=(B[i]==""?0:B[i]); + if (va+0 > vb+0) exit 0; + if (va+0 < vb+0) exit 1; + } + exit 1; + }' +} + +get_system_arch() { + local arch + arch=$(uname -m 2>/dev/null || echo "") + [ "$arch" = "x86_64" ] && arch="amd64" + [ "$arch" = "aarch64" ] && arch="arm64" + echo "$arch" +} + +create_temp_dir() { + mktemp -d +} + +get_os_info() { + local field="${1:-all}" + [ -z "${_OS_ID:-}" ] && _OS_ID=$(awk -F= '/^ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null) + [ -z "${_OS_CODENAME:-}" ] && _OS_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null) + [ -z "${_OS_VERSION:-}" ] && _OS_VERSION=$(awk -F= '/^VERSION_ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null) + case "$field" in + id) echo "$_OS_ID" ;; + codename) echo "$_OS_CODENAME" ;; + version | version_id) echo "$_OS_VERSION" ;; + all) echo "ID=$_OS_ID CODENAME=$_OS_CODENAME VERSION=$_OS_VERSION" ;; + *) echo "$_OS_ID" ;; + esac +} + +is_alpine() { [ "$(get_os_info id)" = "alpine" ]; } + +get_os_version_major() { + local v + v=$(get_os_info version) + echo "${v%%.*}" +} + +ensure_dependencies() { + need_tool "$@" +} + +download_file() { + local url="$1" output="$2" max_retries="${3:-3}" show_progress="${4:-false}" + local i=1 curl_opts="-fsSL" + [ "$show_progress" = "true" ] && curl_opts="-fL#" + while [ $i -le "$max_retries" ]; do + if curl $curl_opts -o "$output" "$url"; then + return 0 + fi + i=$((i + 1)) + [ $i -le "$max_retries" ] && sleep 2 + done + msg_error "Failed to download: $url" + return 1 +} + +github_api_call() { + local url="$1" output_file="${2:-/dev/stdout}" + local max_retries=3 retry_delay=2 attempt=1 + local header="" + [ -n "${GITHUB_TOKEN:-}" ] && header="-H Authorization:Bearer\ ${GITHUB_TOKEN}" + while [ $attempt -le $max_retries ]; do + http_code=$(curl -fsSL -w "%{http_code}" -o "$output_file" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $header "$url" 2>/dev/null || echo 000) + case "$http_code" in + 200) return 0 ;; + 403) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || { + msg_error "GitHub API rate limit exceeded" + return 1 + } ;; + 404) + msg_error "GitHub API endpoint not found: $url" + return 1 + ;; + *) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || { + msg_error "GitHub API call failed with HTTP $http_code" + return 1 + } ;; + esac + retry_delay=$((retry_delay * 2)) + attempt=$((attempt + 1)) + done + return 1 +} + +extract_version_from_json() { + local json="$1" field="${2:-tag_name}" strip_v="${3:-true}" version + need_tool jq || return 1 + version=$(printf '%s' "$json" | jq -r ".${field} // empty") + [ -z "$version" ] && return 1 + [ "$strip_v" = "true" ] && printf '%s' "${version#v}" || printf '%s' "$version" +} + +get_latest_github_release() { + local repo="$1" strip_v="${2:-true}" tmp + tmp=$(mktemp) || return 1 + github_api_call "https://api.github.com/repos/${repo}/releases/latest" "$tmp" || { + rm -f "$tmp" + return 1 + } + extract_version_from_json "$(cat "$tmp")" "tag_name" "$strip_v" + rc=$? + rm -f "$tmp" + return $rc +} + need_tool() { # usage: need_tool curl jq unzip ... # setup missing tools via apk @@ -78,7 +217,12 @@ check_for_gh_release() { } need_tool curl jq || return 1 - tag=$(curl -fsSL "https://api.github.com/repos/${source}/releases/latest" | jq -r '.tag_name // empty') + github_api_call "https://api.github.com/repos/${source}/releases/latest" "/tmp/${app_lc}-release.json" || { + msg_error "Unable to fetch latest tag for $app" + return 1 + } + tag=$(cat "/tmp/${app_lc}-release.json" | jq -r '.tag_name // empty') + rm -f "/tmp/${app_lc}-release.json" [ -z "$tag" ] && { msg_error "Unable to fetch latest tag for $app" return 1 @@ -115,7 +259,7 @@ check_for_gh_release() { # GitHub: get Release & deployen (Alpine) # modes: tarball | prebuild | singlefile # ------------------------------ -fetch_and_deploy_gh() { +fetch_and_deploy_gh_release() { # $1 app, $2 repo, [$3 mode], [$4 version], [$5 target], [$6 asset_pattern local app="$1" repo="$2" mode="${3:-tarball}" version="${4:-latest}" target="${5:-/opt/$1}" pattern="${6:-}" local app_lc @@ -133,20 +277,21 @@ fetch_and_deploy_gh() { tmpd="$(mktemp -d)" || return 1 mkdir -p "$target" - # Release JSON + # Release JSON (with token/rate-limit handling) if [ "$version" = "latest" ]; then - json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest")" || { + github_api_call "https://api.github.com/repos/$repo/releases/latest" "$tmpd/release.json" || { msg_error "GitHub API failed" rm -rf "$tmpd" return 1 } else - json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/tags/$version")" || { + github_api_call "https://api.github.com/repos/$repo/releases/tags/$version" "$tmpd/release.json" || { msg_error "GitHub API failed" rm -rf "$tmpd" return 1 } fi + json="$(cat "$tmpd/release.json")" # correct Version version="$(printf '%s' "$json" | jq -r '.tag_name // empty')" @@ -173,6 +318,7 @@ fetch_and_deploy_gh() { return 1 } unpack="$(find "$tmpd" -mindepth 1 -maxdepth 1 -type d | head -n1)" + [ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"* # copy content of unpack to target (cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || { msg_error "copy failed" @@ -180,6 +326,34 @@ fetch_and_deploy_gh() { return 1 } ;; + binary) + [ -n "$pattern" ] || pattern="*.apk" + url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" 'BEGIN{IGNORECASE=1} $0 ~ p {print; exit}')" + [ -z "$url" ] && { + msg_error "binary asset not found for pattern: $pattern" + rm -rf "$tmpd" + return 1 + } + filename="${url##*/}" + download_with_progress "$url" "$tmpd/$filename" || { + rm -rf "$tmpd" + return 1 + } + case "$filename" in + *.apk) + apk add --no-cache --allow-untrusted "$tmpd/$filename" >/dev/null 2>&1 || { + msg_error "apk install failed: $filename" + rm -rf "$tmpd" + return 1 + } + ;; + *) + msg_error "Unsupported binary asset on Alpine: $filename" + rm -rf "$tmpd" + return 1 + ;; + esac + ;; prebuild) [ -n "$pattern" ] || { msg_error "prebuild requires asset pattern" @@ -220,6 +394,7 @@ fetch_and_deploy_gh() { return 1 ;; esac + [ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"* # top-level folder strippen if [ "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -z "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type f | head -n1)" ]; then unpack="$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d)" @@ -252,11 +427,13 @@ fetch_and_deploy_gh() { return 1 } filename="${url##*/}" - download_with_progress "$url" "$target/$app" || { + local target_file="$app" + [ "${USE_ORIGINAL_FILENAME:-false}" = "true" ] && target_file="$filename" + download_with_progress "$url" "$target/$target_file" || { rm -rf "$tmpd" return 1 } - chmod +x "$target/$app" + chmod +x "$target/$target_file" ;; *) msg_error "Unknown mode: $mode" @@ -271,6 +448,11 @@ fetch_and_deploy_gh() { msg_ok "Deployed $app ($version) → $target" } +# tools.func compatibility alias +fetch_and_deploy_gh() { + fetch_and_deploy_gh_release "$@" +} + # ------------------------------ # yq (mikefarah) – Alpine # ------------------------------ diff --git a/misc/install.func b/misc/install.func index 591404363..c8d6ae7e1 100644 --- a/misc/install.func +++ b/misc/install.func @@ -551,7 +551,7 @@ get_ip() { # Try hostname -I first (most common) if command -v hostname &>/dev/null; then - ip=$(hostname -I 2>/dev/null | awk '{print $1}') + ip=$(hostname -I 2>/dev/null | awk '{print $1}' || true) fi # Fallback to ip command