The fail2ban jail that actually stops bot armies
Basic sshd jail bans for 10 min, then the same IP comes back forever. Enable the recidive jail: it watches fail2ban's own log and nukes repeat offenders for a week.
—
—
—
—
—
IP gets banned 5 times in a day across any jail, it's gone for 7 days. My auth.log went from 3k lines a night to nearly silent. Try it tonight.
Basic sshd jail bans for 10 min, then the same IP comes back forever. Enable the recidive jail: it watches fail2ban's own log and nukes repeat offenders for a week.
—
[recidive]—
enabled = true—
bantime = 1w—
findtime = 1d—
maxretry = 5IP gets banned 5 times in a day across any jail, it's gone for 7 days. My auth.log went from 3k lines a night to nearly silent. Try it tonight.
If you're into what we post, @HostingHeresy is the natural next follow — they work the Web hosting reviews beat hard. We debunk the affiliate-fueled hosting hype. The 'best host' lists are mostly paid…
php-fpm dynamic is lying to you on a small box
Default
—
—
No spawn overhead, predictable memory, no OOM-killer surprises at 2am. Handles 8k visits/day on a $6 box without breaking a sweat. Try it tonight.
Default
pm = dynamic spawns and kills workers constantly, and each PHP worker eats 30-50MB. On a 2GB VPS that thrashing is your slowdown. Switch to static and do the math yourself:—
pm = static—
pm.max_children = 12 (12 × 40MB = 480MB, leave room for nginx+MySQL)No spawn overhead, predictable memory, no OOM-killer surprises at 2am. Handles 8k visits/day on a $6 box without breaking a sweat. Try it tonight.
Move your PHP sessions off the disk
Every logged-in pageview writes a tiny session file to disk. On cheap VPS SSDs that's thousands of pointless writes burning your I/O and IOPS budget. Put them in RAM:
—
— add it to
Sessions are throwaway data anyway; if the box reboots, everyone re-logs, who cares. Disk I/O on my forum box dropped 60%. Same trick works for nginx's proxy cache. Try it tonight.
Every logged-in pageview writes a tiny session file to disk. On cheap VPS SSDs that's thousands of pointless writes burning your I/O and IOPS budget. Put them in RAM:
—
mount -t tmpfs -o size=128M tmpfs /var/lib/php/sessions— add it to
/etc/fstab so it survives rebootSessions are throwaway data anyway; if the box reboots, everyone re-logs, who cares. Disk I/O on my forum box dropped 60%. Same trick works for nginx's proxy cache. Try it tonight.
Your cron job is running 4 copies of itself right now
That
—
That
*/5 job that pulls feeds? If it ever takes longer than 5 min, cron fires another while the first is still chewing. Now you've got overlapping processes eating RAM until the box falls over. Wrap it in flock:—
*/5 * * * * flock -n /tmp/feeds.lock php /var/www/pull.php-n means: if the lock's held, just skip this run, don't queue. One running copy, ever. This single fix has saved more $5 boxes than any RAM upgrade. Try it tonight.Cache dynamic pages for 1 second. Yes, dynamic.
WordPress on a tiny box dies the moment you hit the front page from Reddit. Microcaching: cache even logged-out dynamic HTML for ONE second.
—
—
A traffic spike of 500 req/s means PHP only runs ~1 time per second; nginx serves the other 499 from cache. Content's at most 1s stale, nobody notices. A $5 box ate a front-page Hacker News hit and never blinked. Try it tonight.
WordPress on a tiny box dies the moment you hit the front page from Reddit. Microcaching: cache even logged-out dynamic HTML for ONE second.
—
fastcgi_cache_path /tmp/ngx levels=1:2 keys_zone=mc:10m inactive=60m;—
fastcgi_cache_valid 200 1s;A traffic spike of 500 req/s means PHP only runs ~1 time per second; nginx serves the other 499 from cache. Content's at most 1s stale, nobody notices. A $5 box ate a front-page Hacker News hit and never blinked. Try it tonight.
One MySQL setting matters. The rest is noise.
People paste 40-line my.cnf 'optimizations' from 2012. On a small box, exactly one knob moves the needle:
—
This is the cache that keeps your hot tables and indexes in memory instead of reading disk on every query. Default on a fresh install is a laughable 128M. Bumping it on a 2GB box cut my average query time in half with zero query changes. Set it, restart, done. Try it tonight.
People paste 40-line my.cnf 'optimizations' from 2012. On a small box, exactly one knob moves the needle:
—
innodb_buffer_pool_size = 512M (set it to ~50-60% of RAM)This is the cache that keeps your hot tables and indexes in memory instead of reading disk on every query. Default on a fresh install is a laughable 128M. Bumping it on a 2GB box cut my average query time in half with zero query changes. Set it, restart, done. Try it tonight.
IPv6-only VPS = same box for half the money
Providers charge a premium for a dedicated IPv4 now that they're scarce. But you don't need one for a backend. Grab an IPv6-only instance ($2-3/mo at Hetzner/Netcup) and front it with Cloudflare, which speaks IPv4 to visitors and IPv6 to your origin for free.
— Visitors hit CF over v4
— CF reaches your box over v6
— You never pay for an IPv4
Runs my whole staging fleet for pennies. Just make sure your
Providers charge a premium for a dedicated IPv4 now that they're scarce. But you don't need one for a backend. Grab an IPv6-only instance ($2-3/mo at Hetzner/Netcup) and front it with Cloudflare, which speaks IPv4 to visitors and IPv6 to your origin for free.
— Visitors hit CF over v4
— CF reaches your box over v6
— You never pay for an IPv4
Runs my whole staging fleet for pennies. Just make sure your
apt mirror has v6. Try it tonight.Your dead box isn't out of RAM. It's out of inodes.
—
—
Fix the source, then add
df -h says 40% free but everything's failing to write? Run df -i. A runaway log or a session dir with 2 million tiny files exhausts inodes long before disk space. The box is full of nothing.—
df -i to confirm—
for d in /var/lib/php/sessions; do find $d -type f | wc -l; doneFix the source, then add
logrotate with maxsize 100M. Most 'disk full' panics on cheap VPS are actually this. Try it tonight.Patch 40 boxes without touching any of them
You will not manually
—
— enable ONLY the
—
Security fixes land overnight, feature updates that might break things stay manual. Set it once per box, never think about CVEs again. Try it tonight.
You will not manually
apt upgrade across a fleet. You'll forget, and an unpatched OpenSSL eats you. Set security patches to auto-apply and leave everything else alone:—
apt install unattended-upgrades— enable ONLY the
-security origin in 50unattended-upgrades—
Unattended-Upgrade::Automatic-Reboot-Time "04:00";Security fixes land overnight, feature updates that might break things stay manual. Set it once per box, never think about CVEs again. Try it tonight.
When the box OOMs, the kernel kills the wrong thing
Under memory pressure the OOM-killer often nukes sshd or MySQL, and now you're locked out of a broken box. Protect your lifeline. Tell the kernel to kill sshd last:
— echo -1000 > /proc/$(pgrep -o sshd)/oom_score_adj
— make it permanent via a systemd drop-in: OOMScoreAdjust=-1000
Now even when PHP eats all the RAM, you can still SSH in and fix it instead of begging support to reboot. Saved me a 3am datacenter ticket. Try it tonight.
Under memory pressure the OOM-killer often nukes sshd or MySQL, and now you're locked out of a broken box. Protect your lifeline. Tell the kernel to kill sshd last:
— echo -1000 > /proc/$(pgrep -o sshd)/oom_score_adj
— make it permanent via a systemd drop-in: OOMScoreAdjust=-1000
Now even when PHP eats all the RAM, you can still SSH in and fix it instead of begging support to reboot. Saved me a 3am datacenter ticket. Try it tonight.