EST. 2026 — Notes from real server work SYSADMIN · SECURITY · AI · DIRECTADMIN Issue 01
THE SYSADMIN ALMANAC
Home / Tags / Shared Host
Shared Host

#Shared Host

30 articles
Hosting
Let Clients Pick Photos on a Web Page Without a Login
Web

Let Clients Pick Photos on a Web Page Without a Login

When the person choosing photos for a website is not comfortable with computers, adding registration and login means the work stops at the login screen. This article covers a photo picker with no authentication at all, but with a server endpoint that checks every value against an allowlist strict enough to leave nothing from arbitrary input, plus limits at every layer and a backup before every write.

#php#javascript#web-security#permissions
8 min read·23 Oct
Writing to DirectAdmin Through Panel Forms When the API Only Reads
DirectAdmin

Writing to DirectAdmin Through Panel Forms When the API Only Reads

Notes on letting a back-office app create and edit hosting packages in DirectAdmin when the official CMD_API only provides read operations, requiring POST requests directly to control panel forms, with verification rules that prohibit regex and two layers of kill switches disabled by default.

#directadmin#shared-host#php#laravel
9 min read·14 Oct
Egress Firewall Breaks Domain Checks — Tests as root Pass
Security

Egress Firewall Breaks Domain Checks — Tests as root Pass

The domain order page reported every name as unavailable, even names I made up. The cause was an outbound DROP policy with port 43 missing from the allowed port list after an operating system migration. The trap was that tests as root passed every time. Testing must use the account that actually runs the app.

#firewall#csf#security#networking
9 min read·10 Oct
tinker Sends Mail but the Web Can't — proc_open Disabled in FPM
DirectAdmin

tinker Sends Mail but the Web Can't — proc_open Disabled in FPM

Sending mail from tinker works perfectly, but submitting the actual form sends nothing, and the mail log has no entries — because CLI and PHP-FPM are not the same PHP environment. Includes a working SMTP AUTH configuration for DirectAdmin hosting and the From rule you must get right.

#mail#smtp#laravel#php
9 min read·8 Oct
Site Not Updating After Deploy — Clear All Five Cache Layers
DirectAdmin

Site Not Updating After Deploy — Clear All Five Cache Layers

The files are uploaded, but the site still shows the old version, even after Ctrl+F5 — because five cache layers sit between the files on disk and what people see, and each needs a different clearing method. This article covers the sequence I use regularly, along with the trap that leaves the site stuck on 500 after clearing the view cache.

#deployment#laravel#php#php-fpm
10 min read·8 Oct
route:cache Turns Every GET into 405 — The Sub-path Trap
DirectAdmin

route:cache Turns Every GET into 405 — The Sub-path Trap

Deployment finished, I ran optimize as the guides suggested, and every page returned 405 Method Not Allowed even though route:list confirmed the routes were correct — a route cache that breaks only on certain servers, how to isolate it in 30 seconds, and three other issues I found while deploying an app under a sub-path.

#laravel#php#deployment#apache
9 min read·7 Oct
One Codebase, Two Roles: Hosted Web, Worker at Home
Linux

One Codebase, Two Roles: Hosted Web, Worker at Home

The whole system used to run on one machine behind a home internet connection. When that machine went down, the team could not use anything. I split it into two roles using the same codebase — the web runs on an always-on host, while heavy work stays on the home machine, which pulls jobs itself, with an atomic job-claim table and an 18-step cutover plan with a rollback path.

#laravel#php#queue#worker
12 min read·6 Oct
A Single-Page PHP and SQLite Document Vault That Keeps Originals
Linux

A Single-Page PHP and SQLite Document Vault That Keeps Originals

A document photo storage app for government submissions, using photos taken on site with a phone. Each upload produces three files—the display image, the original, and saved crop settings—so adjustments can be made later without losing quality, with automatic migration from JSON to SQLite and web server restrictions on folders containing personal data.

#php#sqlite#document#security
9 min read·27 Sep
Static on DirectAdmin: GET Returns 404 but HEAD Returns 200
DirectAdmin

Static on DirectAdmin: GET Returns 404 but HEAD Returns 200

I uploaded a static site to public_html and could not open it. Small files worked, large files returned 404, but HEAD returned 200 for every file. The cause was Laravel's .htaccess at the docroot, funneling everything into the front controller. This article covers the diagnosis and three ways out.

#directadmin#cloudflare#apache#htaccess
9 min read·14 Sep
Auditing prod with real customer data without leaving a single row
Linux

Auditing prod with real customer data without leaving a single row

The system owner asked me to test the entire system on the live server holding customer data without leaving even a single junk row behind. My approach was to bootstrap Laravel myself and call controllers directly inside a transaction that I rolled back, with a COUNT of every table before and after as evidence.

#laravel#php#mysql#mariadb
11 min read·13 Sep
Encrypt Secrets in .env and Decrypt Them When Config Loads
Security

Encrypt Secrets in .env and Decrypt Them When Config Loads

How to store passwords and API keys as ciphertext in Laravel's .env and have config decrypt them on load, using a single helper that detects encrypted values, plus the APP_KEY mismatch across environments that can bring everything down if you get it wrong.

#laravel#php#security#encryption
9 min read·18 Aug
Laravel Queues on Shared Hosting — Don't Share Redis with Cache
Linux

Laravel Queues on Shared Hosting — Don't Share Redis with Cache

If you're enabling queues for Laravel on shared hosting and planning to separate the queue from cache with different REDIS_DB numbers, that won't help. maxmemory and eviction apply to the whole instance, not individual DBs. This article explains why I chose the database driver instead, with complete systemd units to replace Supervisor.

#laravel#redis#queue#systemd
10 min read·17 Aug
Laravel Behind a Proxy Sees 127.0.0.1 — Silent Form, No Error
DirectAdmin

Laravel Behind a Proxy Sees 127.0.0.1 — Silent Form, No Error

A contact form on DirectAdmin says the sender is not human, sends no mail, and leaves every log silent — the cause is Laravel behind nginx-to-apache seeing $request->ip() as 127.0.0.1, failing the bot check and returning before the mail is sent, with an explanation of why TrustProxies must not use '*'

#laravel#php#nginx#php-fpm
9 min read·16 Aug
WAF Returns 406 for Thai Text in POST: Fixing It Without Root
Security

WAF Returns 406 for Thai Text in POST: Fixing It Without Root

ModSecurity on the host returns 406 for certain Thai sentences in the POST body, preventing forms from saving — but as a hosting tenant, I cannot change the rules myself. This article shows how to isolate the offending text through black-box testing, then work around it with JS encoding on submit + middleware decoding in Laravel.

#modsecurity#waf#laravel#php
9 min read·15 Aug
MariaDB on defaults — a 128M buffer pool on a 55 GB RAM server
Linux

MariaDB on defaults — a 128M buffer pool on a 55 GB RAM server

A 16 core server with 55 GB RAM and an SSD, but MariaDB still had the default 128 MB buffer pool. The result was 50 million disk reads in 5 days. The full before-and-after settings, service name and config path traps on DirectAdmin/Debian, rollback steps, and another 500 MyISAM tables waiting for conversion.

#mariadb#mysql#performance#tuning
10 min read·13 Aug
AI Crawler Overloads ?add-to-cart= — Block It Without Hurting SEO
Security

AI Crawler Overloads ?add-to-cart= — Block It Without Hurting SEO

Server load triggered an email alert. The logs showed that 84% of the day's traffic came from one AI crawler following add-to-cart links for every product. I added layers of protection with robots.txt, rel=nofollow and nginx limit_req while keeping all product pages indexable.

#nginx#security#wordpress#seo
10 min read·12 Aug
Stolen Mailbox Password Sent 1,786 Spam Emails Unseen by CSF/LFD
Security

Stolen Mailbox Password Sent 1,786 Spam Emails Unseen by CSF/LFD

A real case of a stolen mailbox password used to send 50-75 spam emails a day, below a limit of 200, for 4 straight weeks without a single response from CSF/LFD/BFM because they only count failed authentication attempts, with the decisive question of whether an account was compromised or merely under attack, exim forensic commands, and a blocklist removal playbook

#mail#exim#security#csf
11 min read·7 Aug
One Query Hung for 54 Minutes, Causing Sitewide 504s via MyISAM Locks
Linux

One Query Hung for 54 Minutes, Causing Sitewide 504s via MyISAM Locks

A single 30 MB table caused 504s on every page across the site, even with 9.5 GB of RAM still free — I traced information_schema.PROCESSLIST to a single SELECT that had been stuck for 54 minutes on a MyISAM table, cascading into metadata locks across the server, with an immediate fix and ways to prevent it from happening again.

#mariadb#mysql#myisam#innodb
10 min read·6 Aug
Set DirectAdmin Admin Backup Cron from the CLI Without the Panel
DirectAdmin

Set DirectAdmin Admin Backup Cron from the CLI Without the Panel

CMD_ADMIN_BACKUP takes five steps to set up a cron job, but DirectAdmin actually just appends one line to backup_crons.list and lets dataskq pick it up. Here is how to write directly to the file from the CLI, including common traps with when=now, base64, and append_to_path.

#directadmin#backup#automation#cron
8 min read·24 Jul
Auditing a Deployed Laravel Site — 3 Layers in Priority Order
Security

Auditing a Deployed Laravel Site — 3 Layers in Priority Order

After deploying Laravel to production, check security in 3 layers — probe externally for exposed endpoints, check files/permissions on the server, then grep for vulnerabilities in the code. This article provides commands and P0-P2 priorities for deciding what to fix first.

#security#hardening#php-fpm#cloudflare
8 min read·17 Jul
Mail Checks Ban the Whole Office—Fixing It with Login Auto-Whitelist
Security

Mail Checks Ban the Whole Office—Fixing It with Login Auto-Whitelist

Real mail clients behave exactly like bots — office machines keep retrying old passwords until CSF bans the whole office. This article covers an auto-whitelist system that watches for successful logins + Thai GeoIP, then grants a temporary allow for 24 hours, along with 5 pitfalls I learned the hard way.

#csf#firewall#mail#exim
9 min read·10 Jul
Per-user Redis on shared hosting—and the maxmemory bug that hung sites
Linux

Per-user Redis on shared hosting—and the maxmemory bug that hung sites

Designing one Redis instance per user on shared hosting with a systemd template + cgroup — and lessons from a maxmemory bug where setting it above the cgroup limit caused intermittent WooCommerce hangs, plus the 80% rule and a guard script to prevent recurrence

#redis#cache#systemd#cgroup
10 min read·9 Jul
WordPress 500s, Empty debug.log — The Fatal Is in the Apache Log
DirectAdmin

WordPress 500s, Empty debug.log — The Fatal Is in the Apache Log

WordPress returns 500 only on portfolio pages, but debug.log is empty — because the fatal error during theme rendering happens before WP logging is ready. The answer is in the apache error log (proxy_fcgi), along with a fix for a child theme with a stale template copied from an older parent version.

#wordpress#php-fpm#debugging#logging
8 min read·8 Jul
Legacy Apps Break After Migration — MariaDB Strict Mode Errors
Linux

Legacy Apps Break After Migration — MariaDB Strict Mode Errors

After moving a website from an old server to a new one, the registration form breaks even though the code has not changed — the cause is STRICT_TRANS_TABLES in the sql_mode of newer MariaDB versions, with fixes at 3 levels, from conf.d to per-app SET SESSION

#mariadb#mysql#migration#server-migration
7 min read·7 Jul
Lost the .com: Move to .net on DirectAdmin Without Data Loss
DirectAdmin

Lost the .com: Move to .net on DirectAdmin Without Data Loss

A .com domain expired and ended up with a domain squatter — how I moved the whole site (files/mail/DNS/SSL) to a new .net domain on DirectAdmin with a single CMD_CHANGE_DOMAIN command, plus 4 follow-up tasks that do not happen automatically

#directadmin#dns#ssl#letsencrypt
9 min read·6 Jul
Managing Linux Servers Safely with AI over SSH
AI

Managing Linux Servers Safely with AI over SSH

How I actually use Claude to audit and fix Linux server security over SSH, from preparing my machine and storing secrets to hard rules before touching production

#claude-code#ssh#ssh-hardening#security
13 min read·12 Jun
Per-User Redis on DirectAdmin Without Buying pro_pack
DirectAdmin

Per-User Redis on DirectAdmin Without Buying pro_pack

How to set up per-user Redis object cache on DirectAdmin shared hosting with a systemd template + unix socket + cgroup limit, using a custom provisioning script instead of the DA panel that requires a pro_pack license, with connection recipes for WordPress, Flarum, and Laravel

#redis#cache#directadmin#shared-host
12 min read·20 May
Tuning ModSecurity on DirectAdmin for Shared Hosting
Security

Tuning ModSecurity on DirectAdmin for Shared Hosting

The 4 additions I made beyond DA defaults — exclusions before CRS, a 1-hit credscan ban, a fix for the incorrect MODSEC_LOG path shipped by DA, and a self-heal cron to recover from rebuild overwrites

#modsecurity#csf#directadmin#custombuild
11 min read·20 May
DA Migration Part 3 — DirectAdmin + CustomBuild on Debian 12
DirectAdmin

DA Migration Part 3 — DirectAdmin + CustomBuild on Debian 12

Installing DirectAdmin through setup.sh, then assembling a stack with multiple PHP versions, MariaDB, ModSecurity, and rspamd using CustomBuild on a staging VM behind NAT, including pitfalls I ran into myself.

#directadmin#custombuild#php-fpm#mariadb
11 min read·20 May
CSF Auto-Unblock for Ghost Devices Amid Botnet Brute Force
Security

CSF Auto-Unblock for Ghost Devices Amid Botnet Brute Force

A real case on a DA shared host where a ghost device in an office got the entire office blocked by CSF every morning. I explain a 4-layer auto-unblock setup that distinguishes office devices from a botnet without accidentally unblocking attackers.

#csf#firewall#brute-force#security
11 min read·20 May