root-ubuntu: give a box with no swap 2G of it - #36
Merged
Conversation
Every box this script provisions was running with zero swap, so the kernel's only answer to a memory spike was the OOM killer -- and what it picks is whatever was biggest, which on a dev box is the build, the language server, or the editor somebody was working in. 2G does not make a small box a big one; it turns "the process died" into "that got slow for a moment". A swapfile rather than a partition: provider images arrive with the whole disk given to /, so there is no partition to make, and a file can be resized or removed on a live box. The step converges like the rest of the script. It only ever acts on a box with NO swap at all, so a machine with a swap partition or zram is left alone rather than gaining a second, forgotten swapfile; the fstab entry is matched on the path, so a re-run adds nothing and a hand-edited line survives. It declines where a plain swapfile is wrong (btrfs needs chattr +C and no compression) or dangerous (a swapfile on zfs can deadlock the box under exactly the pressure it was added to survive), inside a container, where the kernel and its swap belong to the host, and when the disk cannot spare the space -- a full / breaks things a memory spike never would have. vm.swappiness goes to 10 with it. The default of 60 treats swap as another tier of memory and pages out pages that are still in use, which is how swap earns its reputation; 10 keeps it as the safety net. Two details worth keeping: the mode goes on before the chown and on its own, because chained behind a failing chown the file would stay readable and mkswap would still accept it, and swap is every secret the machine has ever paged out. And a failed mkswap or swapon removes the file, so a later run cannot mistake 2G of dead disk for working swap. SWAP_SIZE=0 turns the whole thing off. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013TerE4nvNU3jvS51nRR6Pd
ThreatCrush Security Scan16 finding(s) HIGH/CRITICAL: 5 | MEDIUM: 2 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
ralyodio
added a commit
that referenced
this pull request
Aug 30, 2026
Eight commits since 0.15.0, one of them a new command, so the minor moves. - sysupdate: apt lists, apt packages and snaps in one command, reachable from the pit as /update (#37) - root-ubuntu.sh: a 2G swapfile on a box with no swap at all, plus vm.swappiness=10 (#36) - root-ubuntu.sh: one ssh-agent per user under systemd (#35) - root-ubuntu.sh: lm-sensors, smartmontools and the rest of the hardware inventory set, with sensor detection on bare metal - companions: diskpush, and installers that are not npm (#34) - porkbun: Porkbun's own pre-flight, structured refusals, and the fact that registration spends prepaid credit rather than a card (#32, #33) Claude-Session: https://claude.ai/code/session_013TerE4nvNU3jvS51nRR6Pd Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every box this script provisions was running with zero swap. Checked before writing anything:
dev(dev.profullstack.com)seed2=dev.chovy.com(152.53.47.37, one box)seed1(104.152.209.195)With no swap the kernel's only answer to a memory spike is the OOM killer, and what it picks is whatever was biggest — on a dev box that is the build, the language server, or the editor somebody was working in.
What the step does
A swapfile, not a partition: provider images arrive with the whole disk given to
/, so there is no partition to make, and a file can be resized or removed on a live box.It converges like the rest of the script:
chattr +Cand no compression; a swapfile on zfs can deadlock the box under exactly the pressure it was added to survive/breaks things a memory spike never would havevm.swappinessgoes to 10 alongside it. The default of 60 treats swap as another tier of memory and pages out pages that are still in use, which is how swap earned its reputation.Two details worth keeping:
mkswapwould still accept it — and swap is every secret the machine has ever paged out.mkswaporswaponremoves the file, so a later run cannot mistake 2G of dead disk for working swap.SWAP_SIZE=0turns the whole thing off.SWAP_SIZE/SWAP_FILE/SWAPPINESSare documented in--helpandserver.conf.example.Verification
Applied to
devandseed2by running the committed code, then checked on the boxes:A second run on
devreportedswap already active: /swapfile (file, 2G)and changed nothing.17 new tests in
test/root-ubuntu.test.ts(100 in that file, 560 across the suite, all passing). They stubswapon/mkswap/df/systemd-detect-virtand rewrite the two absolute paths into a temp dir withdeclare -f, so the code under test is the code in the file and the test cannot touch the machine it runs on.bash -nand shellcheck are clean; the twotscerrors insrc/free-names.tsare pre-existing onmaster.Not done: seed1
seed1.h4kr.comstill has no swap. Root SSH is permitted there but neither key on the dev box is in root'sauthorized_keys, and theubuntuaccount's sudo wants a password. Needs either that password or our key added to root — then the same step applies.🤖 Generated with Claude Code
https://claude.ai/code/session_013TerE4nvNU3jvS51nRR6Pd