right-size app memory limits via Cloudron API [#685]
Staged during the postgres/connection exhaustion fix; limits had grown to 160GB total on a 62GB box while chasing the flapping. Plan/canary/apply modes, ~28GB of slider headroom reclaim.
This commit is contained in:
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# cloudron-memlimits.sh - right-size app memory limits [#685]
|
||||||
|
# Reads CLOUDRON_URL + CLOUDRON_TOKEN from ~/.creds/cloudron.env
|
||||||
|
# Usage: cloudron-memlimits.sh [canary|apply|plan]
|
||||||
|
# plan (default) show current vs proposed, change nothing
|
||||||
|
# canary apply axiosheartstudios.com only, then verify
|
||||||
|
# apply apply all proposals
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ENV_FILE="$HOME/.creds/cloudron.env"
|
||||||
|
[ -f "$ENV_FILE" ] || { echo "missing $ENV_FILE"; exit 1; }
|
||||||
|
. "$ENV_FILE"
|
||||||
|
: "${CLOUDRON_URL:?}" "${CLOUDRON_TOKEN:?}"
|
||||||
|
|
||||||
|
MODE="${1:-plan}"
|
||||||
|
|
||||||
|
# fqdn:new-limit-MB (from #685 census 2026-09-02, steady-state based)
|
||||||
|
PROPOSALS="
|
||||||
|
axiosheartstudios.com:512
|
||||||
|
community.turnsys.com:4096
|
||||||
|
nextcloud.knownelement.com:2048
|
||||||
|
bookmarks.knownelement.com:2048
|
||||||
|
photos.knownelement.com:3072
|
||||||
|
share.knownelement.com:512
|
||||||
|
hfnfc.net:512
|
||||||
|
notes.knownelement.com:1024
|
||||||
|
office-onlyoffice.knownelement.com:1536
|
||||||
|
paperless.knownelement.com:2048
|
||||||
|
file-transfer.knownelement.com:512
|
||||||
|
digital-assets-manager.knownelement.com:512
|
||||||
|
pwvault.turnsys.com:512
|
||||||
|
finance.turnsys.com:512
|
||||||
|
finance.reachableceo.com:512
|
||||||
|
cmdb.knownelement.com:512
|
||||||
|
"
|
||||||
|
|
||||||
|
api() {
|
||||||
|
curl -s -m 30 -H "Authorization: Bearer $CLOUDRON_TOKEN" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
APPS=$(api "$CLOUDRON_URL/api/v1/apps?per_page=200")
|
||||||
|
echo "$APPS" | jq -e '.apps' >/dev/null 2>&1 || { echo "API auth/list failed"; exit 1; }
|
||||||
|
|
||||||
|
reclaimed=0
|
||||||
|
for line in $PROPOSALS; do
|
||||||
|
fqdn=${line%%:*}; newmb=${line##*:}
|
||||||
|
match=$(echo "$APPS" | jq -r --arg f "https://$fqdn" \
|
||||||
|
'.apps[] | select(.fqdn==$f or (.domain==$f and (.location=="" or .location=="@"))) | "\(.id) \(.memoryLimit)"' | head -1)
|
||||||
|
[ -z "$match" ] && { echo "SKIP $fqdn (not an app)"; continue; }
|
||||||
|
appid=${match%% *}; curmb=$(( ${match##* } / 1048576 ))
|
||||||
|
[ "$curmb" -le "$newmb" ] && { echo "SKIP $fqdn (already $curmbMB <= $newmb)"; continue; }
|
||||||
|
|
||||||
|
case "$MODE" in
|
||||||
|
plan)
|
||||||
|
echo "PLAN $fqdn: ${curmb}MB -> ${newmb}MB (reclaim $((curmb - newmb))MB)"
|
||||||
|
;;
|
||||||
|
canary)
|
||||||
|
[ "$fqdn" != "axiosheartstudios.com" ] && continue
|
||||||
|
echo "CANARY $fqdn: ${curmb}MB -> ${newmb}MB"
|
||||||
|
api -X POST "$CLOUDRON_URL/api/v1/apps/$appid" -H 'Content-Type: application/json' \
|
||||||
|
-d "{\"memoryLimit\": $((newmb * 1048576))}" | jq -r '.status // .message // .'
|
||||||
|
;;
|
||||||
|
apply)
|
||||||
|
echo "APPLY $fqdn: ${curmb}MB -> ${newmb}MB"
|
||||||
|
api -X POST "$CLOUDRON_URL/api/v1/apps/$appid" -H 'Content-Type: application/json' \
|
||||||
|
-d "{\"memoryLimit\": $((newmb * 1048576))}" | jq -r '.status // .message // .'
|
||||||
|
sleep 8
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
reclaimed=$((reclaimed + curmb - newmb))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "---"
|
||||||
|
echo "mode=$MODE total-limit-reclaim=${reclaimed}MB"
|
||||||
Reference in New Issue
Block a user