Make swapfile a default for every install, not just Asterisk droplets

Extracts the swapfile logic out of services/asterisk.sh (previously
DigitalOcean-droplet-gated) into lib/common.sh's ensure_swapfile() —
provider detection was never really the point, the actual condition
that matters is "modest RAM, no swap yet," which applies just as much
to a non-DO VPS running several Docker services at once as it did to a
single-purpose droplet.

- lib/common.sh: new ensure_swapfile(), same fallocate/mkswap/fstab/
  swappiness logic as before, threshold raised from 2048MB to 4096MB
  (a 4GB box running a full service stack is exactly the case that
  motivated this change — the old threshold would have skipped it).
- services/base.sh: calls it unconditionally so every install gets the
  same check regardless of which other services get chosen.
- services/asterisk.sh: swapfile call is no longer gated behind
  IS_DO — calls the shared helper directly. Kept a standalone-mode
  stub (same pattern as this file's other stubbed helpers) so
  `sudo bash asterisk.sh` with no base.sh in the picture still gets
  it. Idempotent either way: a box that already has swap, or already
  got it from base.sh earlier in the same run, no-ops immediately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBtExJcqxnokyZZKmphdug
This commit is contained in:
Claude
2026-08-09 18:13:37 +00:00
parent 7a66ef2e2f
commit ad38b96cfe
3 changed files with 102 additions and 51 deletions
+41
View File
@@ -268,6 +268,47 @@ ensure_ufw_enabled() {
log_success "UFW enabled (SSH on port ${_ssh_port} allowed first, so this won't lock you out)."
}
# Adds a swapfile on any box with modest RAM and no swap already active —
# no cloud-provider detection, just the actual condition that matters. Used
# to be DigitalOcean-droplet-gated logic living only in services/asterisk.sh;
# generalized here so every install gets the same safety net regardless of
# which services get chosen or which provider the box is on — a small VPS
# running several Docker services at once needs this just as much as a
# single-purpose Asterisk droplet did. Idempotent and safe to call from
# multiple places in the same run (services/base.sh calls it for every
# install; services/asterisk.sh also calls it directly so the standalone
# `sudo bash asterisk.sh` path — no base.sh involved — still gets it): a
# box that already has swap, or already got it from an earlier call in the
# same session, just returns immediately.
ensure_swapfile() {
local TOTAL_RAM_MB
TOTAL_RAM_MB="$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
[[ "$TOTAL_RAM_MB" -gt 0 && "$TOTAL_RAM_MB" -le 4096 ]] || return 0
swapon --show | grep -q . && return 0
[ "$DRY_RUN" = true ] && { echo "[DRY-RUN] Would add a swapfile (${TOTAL_RAM_MB}MB RAM, no swap detected)"; return 0; }
local FREE_DISK_MB SWAP_MB=2048
FREE_DISK_MB="$(df -Pm / | awk 'NR==2 {print $4}')"
if [[ "$FREE_DISK_MB" -le $((SWAP_MB + 2048)) ]]; then
log_warning "Not enough free disk for a safe swapfile (${FREE_DISK_MB}MB free) — skipping."
log_warning "Consider a bigger box, or free up disk before installing."
return 0
fi
local ADD_SWAP=""
prompt_yn "No swap detected on this ${TOTAL_RAM_MB}MB-RAM box — add a ${SWAP_MB}MB swapfile? (recommended) (y/n):" "y" ADD_SWAP
[[ "$ADD_SWAP" =~ ^[Yy]$ ]] || return 0
fallocate -l "${SWAP_MB}M" /swapfile 2>/dev/null || dd if=/dev/zero of=/swapfile bs=1M count="$SWAP_MB" status=none
chmod 600 /swapfile
mkswap /swapfile >/dev/null
swapon /swapfile
grep -q '^/swapfile ' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab
grep -q '^vm.swappiness' /etc/sysctl.conf 2>/dev/null || echo 'vm.swappiness=10' >> /etc/sysctl.conf
sysctl -w vm.swappiness=10 >/dev/null 2>&1
log_success "Swapfile enabled (${SWAP_MB}MB, swappiness=10, persists across reboots)."
}
# Scopes a UFW allow rule to just the caddy_net bridge subnet instead of
# every interface. Needed for any port that only needs to be reachable from
# a *locally* Caddy-fronted service (via host.docker.internal) — a plain