EST. 2026 — Notes from real server work SYSADMIN · SECURITY · AI · DIRECTADMIN Issue 01
THE SYSADMIN ALMANAC

All articles

165 articles
Passing the Sandbox Doesn't Mean It Works — 7 False Signals
Linux

Passing the Sandbox Doesn't Mean It Works — 7 False Signals

The automated ordering system I wrote passed every command in a provider's sandbox, but almost everything the sandbox told me differed from reality, from response times and charges to accepted names and items that were created successfully but could not be found. Here are 7 false signals and how to write code that does not fall for them.

#api#rest-api#testing#debugging
9 min read·26 Oct
Cross-Model Audits of AI-Written Code — Process, Not Faith
AI

Cross-Model Audits of AI-Written Code — Process, Not Faith

After using AI to port a calculator from a 35-sheet engineering spreadsheet, how do I know it is correct? This article covers three independent audit rounds by an agent from another provider, the rules to set before starting, confidence levels that keep claims within the evidence, and the classes of errors AI kept making in every round.

#ai#llm#ai-agent#claude-code
9 min read·26 Oct
Labels Printing Off-Center? Calibrate the Print Offset Once
Hardware

Labels Printing Off-Center? Calibrate the Print Offset Once

After getting the label printer to fire its printhead, the next problem was that the text missed the sticker. I stopped guessing and printed rulers and corner markers to measure it, then clearly separated paper size, printable area, and offset into three distinct values.

#printer#kotlin#android#hardware
9 min read·25 Oct
Bank Open API QR Payments — From Sandbox to Status Lifecycle
Web

Bank Open API QR Payments — From Sandbox to Status Lifecycle

A static PromptPay QR is easy to build yourself, but nothing tells you whether the customer has paid. This article walks through a bank's Open API sandbox, from requesting a token and issuing a dynamic QR to tracking REQUESTED/PAID/CANCELLED/VOIDED states and the requestDt trap that rejects requests even when the entire payload is correct.

#api#rest-api#payment#qrcode
10 min read·25 Oct
Drawing SVG Electrical Panels You Can Measure on Paper
Hardware

Drawing SVG Electrical Panels You Can Measure on Paper

The electrical panel drawings I generated from HTML looked good, but the technician said the proportions were wrong. I rebuilt the whole sheet, anchored it to actual catalog dimensions, wrote the viewBox directly in millimeters, and added a scale bar so the technician could use a ruler to verify that the drawing in hand really was at 1:10.

#drafting#cad#electrical#printing
9 min read·24 Oct
Silent Overwrites on Upload: Three File Copying Traps
Linux

Silent Overwrites on Upload: Three File Copying Traps

Upload two files with the same name together, and the second silently overwrites the first. No error, no failing exit code, and every page still returns 200. The English page just becomes a Thai page. These are three traps that let file copying cause damage without any warning.

#deployment#pscp#plink#putty
8 min read·24 Oct
Migrating an Old .aspx Site to a JSON Catalog and Filtering Images
Web

Migrating an Old .aspx Site to a JSON Catalog and Filtering Images

The owner of an old .aspx site asked me to rebuild it, but more than a decade of content was in a database I could no longer access. I collected the pages from the site itself to build a JSON catalog that preserved every legacy_id, then wrote a three-layer image filter to keep stray QR codes from becoming article covers.

#python#web-scraping#crawler#migration
10 min read·23 Oct
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
Build APM on Windows: Apache + PHP 8.4 + MariaDB Series Index
Web

Build APM on Windows: Apache + PHP 8.4 + MariaDB Series Index

A 7-part series on compiling Apache 2.4.69, PHP 8.4.27 and MariaDB 11.8.9 from source on Windows 11, so when PHP releases a security patch, I can change the version number in one file and rebuild within a day. This page covers the contents, overview, time, disk space and three-command shortcut.

#devops#php#apache#mariadb
9 min read·22 Oct
Build APM on Windows, Part 7: Deploy, Run, and Apply Security Patches
Web

Build APM on Windows, Part 7: Deploy, Run, and Apply Security Patches

The final part of the series on building Apache + PHP + MariaDB on Windows. Install into C:\APM, start and test it for the first time, open it to the LAN safely, walk through six real bugs (PidFile, MariaDB plugins, the DB port, the ASLR 500, paths with spaces and brackets), and cover the procedure for the next security release.

#devops#windows#apache#php
20 min read·22 Oct
Build APM on Windows Part 6: PHP 8.4 with redis and imagick
Web

Build APM on Windows Part 6: PHP 8.4 with redis and imagick

Part 6 of the series on building Apache + PHP + MariaDB on Windows from source walks through 30-php.ps1 step by step, from php-sdk and the full configure command to copying DLLs and testing that JIT, redis and imagick actually work.

#php#windows#powershell#tutorial
14 min read·22 Oct
Build APM on Windows, Part 5: Compile ImageMagick 7 for PHP imagick
Web

Build APM on Windows, Part 5: Compile ImageMagick 7 for PHP imagick

Part 5 of the Build APM on Windows series compiles ImageMagick 7.1.2-34 and around 40 delegate libraries from source with the official toolchain, including the channel mask patch from 64 to 32 that lets imagick build, and why HEIC cannot be written

#windows#php#devops#powershell
14 min read·22 Oct
Build APM on Windows, Part 4: Compile MariaDB 11.8 LTS
Web

Build APM on Windows, Part 4: Compile MariaDB 11.8 LTS

Part 4 of the Build APM on Windows series walks through compiling MariaDB 11.8.9 from source with CMake and Ninja, from preparing the tools and running the script to testing on port 3399 and explaining why collation must be pinned to utf8mb4_unicode_ci

#mariadb#windows#devops#powershell
14 min read·22 Oct
Build APM on Windows, Part 3: Apache httpd 2.4.69 with CMake
Web

Build APM on Windows, Part 3: Apache httpd 2.4.69 with CMake

Build APR, APR-util, httpd 2.4.69 and mod_fcgid with CMake and Ninja on Windows. Explain why each option is set, use dumpbin to find the DLLs needed beside httpd.exe, prevent links to debug DLLs, and test the config with httpd -t.

#apache#windows#web-server#cpp
14 min read·22 Oct
Build APM on Windows, Part 2: Fetch Source and Libs with vcpkg
Web

Build APM on Windows, Part 2: Fetch Source and Libs with vcpkg

Steps 1 and 2 of building Apache yourself on Windows. Read 00-fetch.ps1 and 10-deps-vcpkg.ps1 line by line, verify the sha256 of every source archive, then have vcpkg build OpenSSL 3.5 LTS and 8 other libs from source, with commands to check the results at every step.

#devops#windows#apache#powershell
14 min read·22 Oct
Build APM on Windows, Part 1: Prepare Tools and Unpack the Build Kit
Web

Build APM on Windows, Part 1: Prepare Tools and Unpack the Build Kit

The first part of a series on building Apache + PHP 8.4 + MariaDB yourself on Windows. Install Visual Studio 2022 Build Tools with the required components, Git, CMake, Ninja and PowerShell 7, configure Defender, unpack the build kit into C:\apm-build, then examine the folders, versions.json and the lib.ps1 and build-all.ps1 scripts line by line.

#windows#devops#powershell#cpp
14 min read·22 Oct
Two Critical PHP RCE Flaws (php2shell): Patch Today
Security

Two Critical PHP RCE Flaws (php2shell): Patch Today

CVE-2026-109618 and CVE-2026-109619 are PHP RCE vulnerabilities with a CVSS score of 9.2 and public exploits already available. They affect every machine using PHP to handle web requests. The patched versions are 8.5.12, 8.4.27, 8.3.36, and 8.2.35. This note covers version checks, updates on Debian, RHEL, DirectAdmin, Docker, and Windows, and temporary settings while waiting for patches.

#cve#php#security#rce
10 min read·22 Oct
Scripting Government PDF Forms and Making Safer ID Copies
AI

Scripting Government PDF Forms and Making Safer ID Copies

Government PDFs distributed as fillable forms often cannot actually handle Thai text. Subdivided fields let digits run over the borders, and tone marks collide with vowels above the line. This article covers listing field names first, filling the fields and flattening them into page content, drawing Thai text with a font that includes all the vowel marks, and making actual-size ID copies with purpose-specific watermarks.

#pdf#python#document#printing
10 min read·22 Oct
Building a Graph API Page App with Three Required Endpoints
Web

Building a Graph API Page App with Three Required Endpoints

When a backend needs to read and reply to Page messages on its own, the only proper route is to build an app and pass the platform's review. This article covers three endpoints the platform requires but people forget until they fail review, the correct way to verify incoming request signatures, and the steps to exchange a short-lived token for a Page token stored outside the web root.

#api#rest-api#php#web-security
10 min read·22 Oct
VM Sees the Dongle but Has No Internet Without a Windows ECM Driver
Hardware

VM Sees the Dongle but Has No Internet Without a Windows ECM Driver

After passing a USB LTE dongle through to a Windows VM, the system sees the device but no network adapter appears. The cause is neither the SIM nor port passthrough, but the dongle exposing a CDC ECM interface that Windows has no built-in driver for, along with storage-mode pitfalls and dhclient overwriting the host's resolv.conf.

#proxmox#hardware#windows#linux
9 min read·21 Oct
A Report Form for a Static Site with No Backend
Web

A Report Form for a Static Site with No Backend

A calculator site made entirely of static files has no server to handle forms, but users still need a way to report mistakes in the formulas. This article covers the one approach I chose—a single worker file that accepts POST requests on one route, verifies Turnstile on the server using the real client IP, accepts images pasted from the clipboard, and sends email from the network edge—along with three traps that cost me an entire night.

#cloudflare#static-site#javascript#web-security
9 min read·21 Oct
Reverse Engineering Spreadsheet Constants into Formulas
AI

Reverse Engineering Spreadsheet Constants into Formulas

A sheet has a criteria table sitting beside the calculations, but no VLOOKUP connects them. People read the table and type values into cells themselves, and mistakes go unnoticed. This article covers separating formula cells from manually entered cells, then reconstructing a single formula that matches all 16 values in a multiplier column.

#spreadsheet#python#reverse-engineering#audit
10 min read·20 Oct
Speed Up Screen Recordings While Keeping the Original Clock
AI

Speed Up Screen Recordings While Keeping the Original Clock

How to make a timelapse from a screen recording by speeding up idle sections more than active sections, using split, trim, and setpts, then joining them with concat. The main trap is that drawtext must come before setpts for the clock to follow the original timeline instead of the accelerated one.

#ffmpeg#video-editing#python#automation
9 min read·20 Oct
A 26-Page Bilingual Site: Why .php Broke Every Link
Web

A 26-Page Bilingual Site: Why .php Broke Every Link

The production page displayed PHP tags as raw text because the web server served .html as static files. Changing all 26 pages to .php broke links across the site. Then, after adding clean URLs, subpages bounced back to .php because the rewrite and 301 setup was only half done. This article includes the full .htaccess, eight cases for $base, and scripts that handle the whole site in one pass.

#htaccess#apache#nginx#php
9 min read·19 Oct
Making 20,000+ API Calls That Resume Without Leaving Corrupt Files
Linux

Making 20,000+ API Calls That Resume Without Leaving Corrupt Files

Generating 26,850 files through an API limited to 20 calls per minute requires three pieces—a system-wide throttle, resuming from what is already on disk, and a separate file validator—because files interrupted by network failures still have the right extension and a nonzero size.

#python#api#rate-limiting#automation
9 min read·19 Oct
A Cookie Banner That Loads GTM and GA4 Only After Consent
Web

A Cookie Banner That Loads GTM and GA4 Only After Consent

Most cookie banners look good but block nothing, because GTM and GA4 have already loaded from the first line of the page. This article covers a setup that loads the container only after acceptance, puts GA4 inside GTM to prevent double counting, hides AdSense slots initially, and checks that outgoing requests to those services stay at zero.

#seo#adsense#javascript#playwright
9 min read·18 Oct
A Blank Page with No Errors, All Because I Named a Function top
Web

A Blank Page with No Errors, All Because I Named a Function top

After deployment, the page was blank, the logs had no errors, and node --check found nothing wrong. But the browser stopped the entire script before the first line ran because a function named top collided with window.top. Here are the names to avoid, the script loading order trap, and the Playwright check every project should have.

#javascript#debugging#troubleshooting#playwright
8 min read·18 Oct
The Monitor That Hammered Devices Until the Whole Farm Went Down
Linux

The Monitor That Hammered Devices Until the Whole Farm Went Down

A monitoring loop that runs every 30 seconds and tries to recover every device that fails a ping sounds useful, until one device hangs and gets hammered repeatedly until the whole bus goes down. This article walks through ruling out hardware, tracking what was accessing the devices, and the settings that fixed it.

#monitoring#linux#python#systemd
10 min read·17 Oct
Images Fail on Mobile in Pages Hidden with display:none
Web

Images Fail on Mobile in Pages Hidden with display:none

A site switches pages using display:none, but opening another page on mobile leaves blank black images, even though the files return 200 and both fetch and new Image succeed. The culprit is the IntersectionObserver behind loading=lazy not firing when the page changes from none to block, and simply setting loading=eager is still not enough.

#javascript#css#mobile-dev#web-performance
9 min read·17 Oct
Reading ID Cards from the Web with a Localhost Agent
Hardware

Reading ID Cards from the Web with a Localhost Agent

Browsers cannot access smart card readers directly. A workable approach is to write a small agent that opens a port on localhost and let the web page call it. This article covers secure contexts, CORS preflight, port conflicts with other agents, PC/SC in SHARED mode, decoding TIS-620 manually, and the day antivirus flagged the program as a backdoor.

#hardware#cpp#windows#gui
11 min read·16 Oct
The NVR Kept Beeping, Then Fell Silent When the Disks Failed
Network

The NVR Kept Beeping, Then Fell Silent When the Disks Failed

The NVR's all-day beeping was not videoloss as everyone thought. It was ipconflict from cameras using DHCP with conflicting IP addresses. Someone got annoyed and muted the whole unit, so when both disks failed together, there was not a single beep. This article fixes the policy one event at a time through ISAPI.

#cctv#nvr#hikvision#isapi
9 min read·16 Oct
Cannot Delete Faces from a Terminal: API Returns notSupport
Hardware

Cannot Delete Faces from a Terminal: API Returns notSupport

The door's face recognition terminal advertises a command to delete faces from FDLib, but every variation I tried returned notSupport. People who had left could still scan their faces and get in. This article covers the dead ends, the approach that actually worked using UserInfo/Modify with the smallest possible body, and the two-way user registry sync that runs every night.

#hikvision#isapi#hardware#python
10 min read·15 Oct
No kWh Meter? Estimate Daily Electricity Costs from Current
Hardware

No kWh Meter? Estimate Daily Electricity Costs from Current

Notes on converting CT current readings into energy usage and daily time-of-use electricity costs, from the three-phase power formula and the sampling interval built into it, through skipping outages and separating peak from off-peak with epoch arithmetic, to a daily summary table that made the web page seven times faster.

#energy#power-meter#electrical#modbus
10 min read·15 Oct
Reading an Unknown Modbus Device: Verify Before Interpreting
Hardware

Reading an Unknown Modbus Device: Verify Before Interpreting

My notes on tracking down an undocumented device on an RS485 bus, from scanning baud rates and addresses one combination at a time to proving which registers hold live values and which are dead, and the lesson that guessing a device's type from number patterns alone can lead to months of misinterpretation.

#modbus#rs485#serial#iot
11 min read·14 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
Registrar and Billing NS Mismatch: Audit All Three Sides First
Network

Registrar and Billing NS Mismatch: Audit All Three Sides First

A debugging log for "Wrong response from the server" when changing nameservers in a billing system, which failed only for domains with leftover glue IP data, followed by a three-way audit of the registrar, billing system, and actual DNS zones before I felt confident changing anything.

#dns#cloudflare#networking#rest-api
9 min read·13 Oct
Ingesting Mail Without Disrupting Someone Else's Mailbox
Linux

Ingesting Mail Without Disrupting Someone Else's Mailbox

The mailbox the app fetches from is one people actually use every day — fetching with UNSEEN silently misses mail when the owner reads it on their phone before cron runs. The right approach is UID SEARCH paired with UIDVALIDITY and BODY.PEEK, with deduplication handled on our side.

#mail#imap#pop3#dovecot
10 min read·13 Oct
Reads from a Replica Must Show How Many Minutes Old the Data Is
Linux

Reads from a Replica Must Show How Many Minutes Old the Data Is

replication can report a lag of 0 seconds while the data is stuck at yesterday, because these two signals measure different things — how to set up a monitor that checks both Seconds_Behind_Master and business data freshness, catches anyone writing directly to the slave, and has another check watching the monitor itself

#mariadb#mysql#monitoring#alerting
9 min read·12 Oct
Let AI Read Documents, but Let Code Do the Math
AI

Let AI Read Documents, but Let Code Do the Math

The controller requires manually entered values to fall between 0 and 100, but the path where AI reads values from documents and feeds them in only checks whether they are numeric. A single negative value inflated the result to 5.25 times what it should have been without an error — a lesson in treating AI output as untrusted input, just like values entered by people.

#ai#llm#claude#claude-code
10 min read·12 Oct
The App Uses UTC, People Use Thai Time — 7 Hours Off, No Errors
Linux

The App Uses UTC, People Use Thai Time — 7 Hours Off, No Errors

Scheduled for three in the afternoon, published at ten at night. No errors, nothing wrong in the logs, because the app stores UTC while the person entering the time thinks in Thai time. This article traces the issue from an env setting that has no effect to the single line that writes Thai wall-clock time into a column everyone reads as UTC.

#laravel#php#mariadb#debugging
9 min read·11 Oct
Moving JSON Time Series to Columns Without Changing the Dashboard
Linux

Moving JSON Time Series to Columns Without Changing the Dashboard

I stored entire device frames as JSON arrays at one row per second. After two weeks, the tables had grown to 183 MB at the endpoint and 625 MB on the server, with JSON_EXTRACT queries that could not use an index — here is how I moved the data into int columns and had the API rebuild a sparse array without changing a single line of the dashboard.

#mariadb#mysql#migration#performance
10 min read·11 Oct
Secrets Set to 600, but 0644 Logs Go Offsite Every Night
Security

Secrets Set to 600, but 0644 Logs Go Offsite Every Night

The .env is encrypted and permissions are locked down on every secret file, but customer data still leaks off the machine every night through something nobody classifies as confidential: logs that every account on the machine can read, bundled into backups uploaded to object storage. Here is how I stop it at the source by logging only result codes.

#security#logging#backup#offsite
10 min read·10 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
Web vs. Worker — mkdir 0700 Disables Inherited ACL Permissions
Linux

Web vs. Worker — mkdir 0700 Disables Inherited ACL Permissions

One app runs as two users, with php-fpm handling web requests and a separate account running the queue. Even with default ACLs fully configured, they still cannot write to each other's directories. The cause is mkdir with mode 0700, which sets a mask that wipes out the effective ACL permissions, plus a deletion trap that requires permissions on the directory, not the file.

#linux#permissions#posix-acl#php-fpm
9 min read·9 Oct
The Service Is Running but Dead — systemd restart Cannot Help
Linux

The Service Is Running but Dead — systemd restart Cannot Help

A long network outage broke DNS. A daemon holding a session with an external API failed to log in 194 times, then hung halfway through the process. It never exited, so the system never restarted it — why I stopped checking whether a process was alive and started measuring data freshness instead.

#systemd#linux#monitoring#alerting
9 min read·9 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
php -l Passes, Web Pages Return 500 — A Compile Gate Before Commit
Linux

php -l Passes, Web Pages Return 500 — A Compile Gate Before Commit

Templates broke twice in one month even though every php -l check passed, because php -l does not understand Blade syntax. This article covers the six-stage gate I put before commit — compiling the views and then linting the compiled files, plus a script that sweeps every GET route through the Kernel.

#laravel#php#blade#testing
9 min read·7 Oct
Always Claim the State Before Sending Anything Out
Linux

Always Claim the State Before Sending Anything Out

A "read the state, then send" guard looks safe until a worker gets killed after sending but before writing to the database, and a retry sends the same thing to the customer twice. This article covers the full set of duplicate prevention measures I use, from atomic claims to retry_after and failed() handlers that must never overwrite a successful state.

#laravel#php#queue#worker
11 min read·6 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
One Tunnel Is the Only Way In—and a Single Point of Failure
Network

One Tunnel Is the Only Way In—and a Single Point of Failure

The machine sits behind NAT with no ports open to the internet. Every way in runs through one cloudflared tunnel — web, SSH, and remote desktop. This article covers the four ingress routes I set up, how to read the signs when it goes down, and the trap that keeps the tunnel from starting at boot.

#cloudflare#cloudflared#tunnel#zero-trust
10 min read·5 Oct
Too Many Alerts Mean No Alerts: Tuning a Bot People Will Read
Linux

Too Many Alerts Mean No Alerts: Tuning a Bot People Will Read

In one day, 28 events became 56 messages, and 57 percent of all events were repeat alerts every 30 minutes. This article covers recipient tiers, merging overlapping cycles, state that survives restarts, and why you must not add keepalive to a chat app session.

#monitoring#alerting#bot#logging
9 min read·5 Oct
Mailbox Compromised or Just Password Guessing? Prove It First
Security

Mailbox Compromised or Just Password Guessing? Prove It First

Telling a customer their account has been compromised is an allegation that needs decisive evidence first. This article covers what counts as decisive evidence, two cases with opposite outcomes, and the case I nearly reported incorrectly.

#mail#mail-forensics#exim#forensics
11 min read·4 Oct
Food Factory Drawings: Sheets, Scales, and Paper Sizes
AI

Food Factory Drawings: Sheets, Scales, and Paper Sizes

A food factory application drawing set has 7 items, each with its own scale range, and some numbers to work out before drawing—how wide a plan will fit on A4 or A3 at 1 to 100, and how to split it across sheets without changing the scale if it will not fit.

#drafting#cad#sketchup#3d-modeling
10 min read·4 Oct
From Model to 6-Meter Steel Cutting Layout and Workshop Cut Sheet
AI

From Model to 6-Meter Steel Cutting Layout and Workshop Cut Sheet

Read part lengths from the model, consolidate duplicates, then arrange a first-fit decreasing cutting layout on standard 6-meter stock with a 3-millimeter saw kerf allowance, plus a notch-and-bend option for right-angle corners that reduces joints from 12 to 6

#structural#steel-design#sketchup#ruby
9 min read·3 Oct
Quantity Takeoff from SketchUp Models with Ruby Scripts
AI

Quantity Takeoff from SketchUp Models with Ruby Scripts

A finished model already contains every number a quantity takeoff needs. Give groups readable names from the start, then write a script to grep through them, with two traps to watch for that can double your areas.

#3d-modeling#sketchup#ruby#drafting
9 min read·3 Oct
SketchUp Drawing Sheets with Automatic Labels and Dimensions
AI

SketchUp Drawing Sheets with Automatic Labels and Dimensions

A finished model is not ready for submission yet. What the authorities accept is a set of paper sheets with building numbers, dimension lines, a north arrow, and a scale. This article covers extracting geometry from the model as numbers, rendering a top ortho view as black lines on white, and letting a script place numbers and dimension lines without overlaps, with overrides for individual items.

#3d-modeling#sketchup#ruby#python
10 min read·2 Oct
Mapping a Building by Phone and Finding True North with GNSS
AI

Mapping a Building by Phone and Finding True North with GNSS

ARCore gives room-corner coordinates in meters accurately enough to use, but its world frame has an unknown orientation, so the resulting plan is always rotated by some angle. The fix is to collect pairs of (AR position, GNSS reading) while working, then fit a rotation using weighted 2D Kabsch, with weights based on each fix's accuracy, to find both north and the origin's coordinates.

#gis#geospatial#mapping#android
10 min read·2 Oct
Rebuilding an Off-Scale PDF Plan at Real Dimensions
AI

Rebuilding an Off-Scale PDF Plan at Real Dimensions

Presentation plans are often drawn block by block, with different scales for the x and y axes and different scales again for each room. Calibrating the whole page once and tracing it gets everything wrong. This article covers extracting coordinates from paper into metres by recalculating the scale for every room, counting objects with colour-blob BFS instead of by eye, and drawing them back into a model at their real dimensions.

#3d-modeling#sketchup#python#pdf
10 min read·1 Oct
Shared Neutrals Across Transformers: Why Phase Balancing Is Not Enough
Hardware

Shared Neutrals Across Transformers: Why Phase Balancing Is Not Enough

A case involving two transformers with interconnected neutrals and houses tapped into one side's main feeder, leaving phase A 30-40 A higher even on days off, plus a meter-reading trap that can suggest a 200 A difference if the CT ratio is not verified first, and a repair sequence that must be followed in order.

#hardware#electrical#power#engineering
9 min read·30 Sep
Sizing Main Cables and Breakers by Installation Method
Hardware

Sizing Main Cables and Breakers by Installation Method

Notes on choosing the main cable and breaker for a new 253 A feeder, why the same size CV cable can carry 227 A or 364 A depending on how it is installed, and the option of downsizing to 95 and compensating with operating rules, at the cost of the main breaker tripping if anyone breaks those rules.

#hardware#electrical#power#engineering
10 min read·29 Sep
Diagnosing Feeder Overload from Melted Insulation and Duty Cycles
Hardware

Diagnosing Feeder Overload from Melted Insulation and Duty Cycles

My investigation of a 95 mm² main cable with insulation melting at scattered points even though the system seemed to work normally, from the nameplates of 6 washers and dryers totaling 234.7 kW to a minute-by-minute current model explaining why a 482 A load on a cable rated for 180 A had not caused a visible system failure.

#hardware#electrical#power#engineering
10 min read·28 Sep
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
Printing Dozens of Government Forms from HTML with Correct Margins
Linux

Printing Dozens of Government Forms from HTML with Correct Margins

A government submission document system where users click Print in their browsers and every sheet must fit within its margins, from measuring the actual printable area in millimeters and repeating headers and footers without position fixed, to four image frame types for different documents and automated overflow checks with Playwright instead of inspecting every sheet.

#pdf#php#css#printing
10 min read·26 Sep
News Stuck for Three Days Because the Feed Wasn't Sorted by Date
Linux

News Stuck for Three Days Because the Feed Wasn't Sorted by Date

The news site's homepage showed the same day's stories for three days straight, even though scheduled jobs ran, translations finished, and every step reported success. The causes were an RSS feed sorted by relevance rather than date, string sorting of pubDate that actually sorted by weekday name, and requesting too few stories, leaving nothing after filtering before the rest even got a look.

#python#javascript#rss#automation
10 min read·25 Sep
Sending Automated Job Files to Telegram and the Bot API's 50 MB Limit
Linux

Sending Automated Job Files to Telegram and the Bot API's 50 MB Limit

Set up a small local service that takes files from scripts and sends them to me on Telegram, with outbound delivery only, no polling, and no incoming commands, along with the actual Bot API limits to know before writing it, including 50 MB per file, images over 10 MB that must be sent as documents, and the Thai text trap in curl on Windows.

#telegram#bot#automation#python
8 min read·24 Sep
CDP Still Responds but Commands Fail After Chrome Updates Itself
Linux

CDP Still Responds but Commands Fail After Chrome Updates Itself

I run several automation jobs on one machine that need a real browser, and ran into two problems at once — jobs fighting over tabs and getting each other's results, and Chrome overwriting its own files during an update while the process was still running, leaving the port responsive but Runtime.evaluate unusable. This article covers how I isolate jobs, detect the failure, and repair it automatically.

#cdp#chromium#automation#windows
9 min read·23 Sep
A 25-Hour Power Outage Left Scheduled Jobs Missing
Linux

A 25-Hour Power Outage Left Scheduled Jobs Missing

The machine running my automated jobs lost power three times in three days, with the longest outage lasting 25 hours. When it came back, I found that jobs scheduled directly through Task Scheduler had skipped their runs entirely, while jobs managed by a dispatcher that checked the time itself had all caught up. This article covers the setting to enable, what to avoid during recovery, and the traps that led me to misread the status.

#windows#scheduler#automation#powershell
9 min read·22 Sep
Automated Image Uploads Stopped for 4 Days: ssh Chosen by PATH
Linux

Automated Image Uploads Stopped for 4 Days: ssh Chosen by PATH

Write subprocess.run(["ssh", ...]) and leave the system to choose the binary from the caller's PATH. One day the caller changes, and the binary changes with it. File transfers fail silently for 4 days while reporting success every time. This article covers how I tracked it down, a helper that probes the actual binary before using it, and a completeness check before declaring the job done.

#ssh#python#automation#scp
9 min read·21 Sep
Tell a Broken Link from an ISP Outage Before Restarting Anything
Linux

Tell a Broken Link from an ISP Outage Before Restarting Anything

A typical watchdog restarts NetworkManager when ping fails, which is wrong half the time because no internet access may mean the ISP is down, not that the adapter has failed. This article distinguishes three states using nmcli, then escalates from gentle recovery to PCI remove and rescan without rebooting the machine.

#linux#networking#systemd#debian
9 min read·20 Sep
Borrowing a VLAN for Windows Tools That Need the Same L2
Network

Borrowing a VLAN for Windows Tools That Need the Same L2

Many manufacturers' device discovery tools use broadcasts that cannot cross L3, so connecting over a VPN still leaves devices invisible. A solution that leaves switch ports alone is to put a small Windows VM on Proxmox with its interface directly in that VLAN, with pitfalls around vlan-aware bridges, a full thin pool breaking other VMs, and virtio leaving Windows without a network adapter after installation.

#proxmox#kvm#vlan#networking
8 min read·19 Sep
Managing Site Switches Remotely with UniFi's Cloud Connector Proxy
Network

Managing Site Switches Remotely with UniFi's Cloud Connector Proxy

My workstation is in a different location from the site, with no VPN and no inbound ports open, but I still need to change VLANs per port, reserve fixed IPs, and track down failing cables. This article explains how Site Manager's connector proxy reaches the legacy API for both reads and writes without requesting a CSRF token, and the discipline needed when holding a key this powerful.

#networking#unifi#rest-api#api
10 min read·18 Sep
Set VLANs on a Hikvision Switch Using Its Web UI API
Network

Set VLANs on a Hikvision Switch Using Its Web UI API

A smart managed switch whose Switch ISAPI endpoints return 403 can still be scripted if you inspect what its web UI sends. This article turns that API into a VLAN configuration script with a dry-run before apply, covering the traps I actually hit, including different field names for reads and writes, CCTV mode forcing 10 Mbps, and a calculated PoE load that exceeds the switch's budget.

#networking#vlan#switch#poe
9 min read·17 Sep
Using an NVR to Reach Inaccessible Cameras with ISAPI and SDK
Network

Using an NVR to Reach Inaccessible Cameras with ISAPI and SDK

The cameras sit behind the NVR's second interface, and none are directly reachable. This article works through what the NVR's ISAPI can actually do, with 26 of 38 tested endpoints working, retrieves CCTV snapshots and RTSP through the NVR, finds when each channel last recorded, and falls back to HCNetSDK through ctypes to read device logs when ISAPI runs out of options.

#cctv#hikvision#nvr#isapi
11 min read·16 Sep
Every Layer Reported Success While the Output Was Garbage
Linux

Every Layer Reported Success While the Output Was Garbage

In one day, four layers of the same automated pipeline failed together, but every layer reported success without a single error line. The person who caught it was a user who said the site was not updating. These are the rules I wrote afterward so that failing stages could speak up for themselves.

#automation#python#monitoring#debugging
10 min read·15 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
Every File Is Backed Up, but I Still Can't Rebuild the Server
Backup

Every File Is Backed Up, but I Still Can't Rebuild the Server

The database dump is complete, the code tar is complete, and all the secrets are there, but put them on a blank machine and the site will not come up, because the things that actually make the server work were never in the backup files. This article lists what disappears with the machine and the recovery sequence I wrote for my future self.

#backup#disaster-recovery#systemd#debian
11 min read·12 Sep
Backups Succeeded Nightly, but Offsite Uploads Failed for 3 Weeks
Backup

Backups Succeeded Nightly, but Offsite Uploads Failed for 3 Weeks

cron ran every night, local files were complete every day, and the log said done, but offsite storage had not changed for 3 weeks. The first 8 nights of backups were already gone for good because local rotation had deleted them first. This article examines the two gaps that let the failure stay silent for so long.

#backup#rclone#s3#cloudflare
10 min read·11 Sep
Generating Thai PDF Quotes with Chromium and the Pitfalls I Hit
Linux

Generating Thai PDF Quotes with Chromium and the Pitfalls I Hit

Building a system to generate PDF quotations from HTML with Chromium for multiple companies in a group and multiple templates, from an Executable doesn't exist error caused by looking for the wrong headless shell, to A4 layout and pagination, sanitizing Thai filenames, and a token-based document numbering system where an accidental slash broke the path.

#pdf#chromium#playwright#python
9 min read·31 Aug
Thai Steel Framing Conventions for Buildable Drawings
AI

Thai Steel Framing Conventions for Buildable Drawings

A steel frame model that looks good on screen but makes a fabricator shake their head usually gets a few conventions wrong—member order, stock sections, stacking instead of interweaving, purlins that must be open C sections, and bearing edges on sloping beams that cause steel to intersect when chosen incorrectly.

#structural#steel-design#sketchup#3d-modeling
9 min read·30 Aug
Moving Computation from PHP to the Browser: 12 Seconds to 12 ms
Linux

Moving Computation from PHP to the Browser: 12 Seconds to 12 ms

A single page ran tens of thousands of subqueries and took 12 seconds to load. I fixed it by precomputing a summary table, sending a single 107 KB dataset, and moving the formulas to the browser, bringing computation down to 12 milliseconds, with a parity test that requires JS results to match PHP on every row.

#performance#php#javascript#laravel
9 min read·29 Aug
Import Land Parcel Boundaries from Government Maps into SketchUp
AI

Import Land Parcel Boundaries from Government Maps into SketchUp

A SketchUp model with Add Location has satellite imagery but no parcel boundaries. This article covers fetching boundaries through OGC-standard WFS, where viewparams is required to avoid getting zero features, converting UTM47 coordinates to WGS84, and placing them in the model with latlong_to_point to line up with the imagery.

#gis#sketchup#ruby#wfs
9 min read·28 Aug
Driving AutoCAD from PowerShell via COM — Scripted Drafting
AI

Driving AutoCAD from PowerShell via COM — Scripted Drafting

AutoCAD exposes COM for scripting just like Excel. Connect to the running instance with New-Object, then draw lines, circles, text, and 3D boxes, create layers, add dimensions, and save files entirely from PowerShell, with four traps I hit myself and learned never to repeat.

#autocad#powershell#com#automation
8 min read·27 Aug
Automating Remote Windows Tasks with SSH + Task Scheduler
Linux

Automating Remote Windows Tasks with SSH + Task Scheduler

Move heavy workloads to a more powerful machine over SSH, then automate them with schtasks — with pitfalls that cost me real time, from landing in PowerShell 5 instead of bash over ssh, to backslashes getting swallowed when writing .bat files, to file transfers hanging until I switched to plink

#windows#ssh#powershell#automation
9 min read·26 Aug
Decoding a Bluetooth Label Printer Protocol from btsnoop
Linux

Decoding a Bluetooth Label Printer Protocol from btsnoop

My Bluetooth label printer only had a mobile app and no way to connect it to my own system, so I enabled HCI snoop logging on my own phone, peeled away HCI/ACL/L2CAP/RFCOMM one layer at a time with a short Python parser, and compared the results with open-source libraries until I could read the commands and print directly from a script.

#bluetooth#ble#python#reverse-engineering
9 min read·25 Aug
Auditing CCTV Directly with ISAPI and ffprobe RTSP, Bypassing the NVR
Network

Auditing CCTV Directly with ISAPI and ffprobe RTSP, Bypassing the NVR

The NVR screen only tells you a camera is online. It does not tell you its model, how old its firmware is, or the actual stream resolution. In this article, I write a script to query ISAPI deviceInfo on each camera directly, then use ffprobe to read values from the actual RTSP stream to build an inventory and check the health of the camera system I maintain.

#cctv#hikvision#python#networking
9 min read·24 Aug
Planning 2.4GHz WiFi Channels 1/6/11 and Multi-Floor Heatmaps
Network

Planning 2.4GHz WiFi Channels 1/6/11 and Multi-Floor Heatmaps

A five-story building with seven APs per floor needs a 2.4GHz channel plan that avoids overlap both horizontally and vertically. This article covers the 1/6/11 principle, per-floor channel tables, the actual Tx power and RSSI threshold settings, and a Python script that labels floor plans with channels using PIL before a walkthrough survey to create a heatmap.

#wifi#networking#rf#python
9 min read·23 Aug
Inventory Switch and AP Ports with SNMP Walk and MAC Tables
Network

Inventory Switch and AP Ports with SNMP Walk and MAC Tables

You can build your own Layer 2 inventory without a controller or NMS. Write an SNMP walk with pysnmp asyncio to retrieve sysDescr, ifTable, and the bridge FDB, then convert OID indexes back into MAC addresses to find which device connects to which port on which switch.

#snmp#networking#python#monitoring
9 min read·22 Aug
Building a Single-Screen Ping Monitor with C++, ImGui and DirectX 11
Network

Building a Single-Screen Ping Monitor with C++, ImGui and DirectX 11

A small app that pings every device on the network at once and puts the results on one screen. It sends ICMP directly through iphlpapi without calling ping.exe, runs one thread per host, communicates with the UI through std::atomic, renders with Dear ImGui on DirectX 11, and builds with CMake and a single PowerShell script.

#cpp#networking#windows#monitoring
9 min read·21 Aug
Read Device Uptime Without SNMP/SSH/API Using TCP Timestamps
Network

Read Device Uptime Without SNMP/SSH/API Using TCP Timestamps

Many IP cameras, door controllers, and embedded devices have no SNMP, SSH, or API for querying uptime. But if they return TCP timestamps, I can read their boot time remotely without logging in even once.

#networking#monitoring#linux#python
7 min read·20 Aug
The Web User's crontab Isn't the One Running Your Jobs
Linux

The Web User's crontab Isn't the One Running Your Jobs

Schedule changes saved through the web still leave jobs running at the old times because the script writes the web user's crontab, not the user’s crontab that cron actually reads. How to spot it in 3 commands, the sudoers drop-in I used, and how to design it so this cannot happen again.

#cron#linux#sysadmin#debugging
7 min read·19 Aug
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
My Firewall Permanently Banned Googlebot and Hid Sites from Search
Security

My Firewall Permanently Banned Googlebot and Hid Sites from Search

I investigated why sites disappeared from search results and found Googlebot in my own firewall's permanent ban list. 408 of 500 entries came from the counter tallying WAF false positives. How I lifted the bans, wrote a script to fetch official bot IP ranges into the ignore list daily, and dealt with a grep trap and the side effects of blocking entire countries.

#csf#firewall#seo#googlebot
10 min read·14 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
Bulk Import Legacy .xls Files into Laravel with PhpSpreadsheet
Linux

Bulk Import Legacy .xls Files into Laravel with PhpSpreadsheet

Legacy .xls files with Thai headers encoded in tis-620 have unreadable column names, large files make PhpSpreadsheet exhaust memory and crash, and files users merge themselves contain duplicate rows — use column positions instead of names, add a read filter, and deduplicate with a natural key.

#php#laravel#excel#phpspreadsheet
9 min read·10 Aug
Factory to Cloud Behind NAT: Push Snapshots and a Command Queue
Network

Factory to Cloud Behind NAT: Push Snapshots and a Command Queue

The production machine sits in a LAN behind NAT with no public IP, but the owner wants to view data on a cloud website and make edits from a phone that reach the internal machine — possible without opening ports or setting up a VPN, using push snapshots + an edit command queue + idempotent acks

#automation#networking#nat#api
10 min read·9 Aug
Repairing a Claude Code Session .jsonl File Too Large to Open at 38 MB
AI

Repairing a Claude Code Session .jsonl File Too Large to Open at 38 MB

A single session stretched over 8 days grew to 38.61 MB / 11,537 records until the UI could no longer open its history. I wrote a Python script to process it line by line, trimming only the parts that were already unreadable to humans, bringing it down to 17.41 MB while preserving all 8,171 message uuid values in their original order, with no orphans.

#claude-code#ai#python#automation
8 min read·8 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
Charset Mismatch Silently Kills JOIN Indexes — an utf8mb4 Mirror
Linux

Charset Mismatch Silently Kills JOIN Indexes — an utf8mb4 Mirror

The old database uses tis620 and the new one uses utf8mb4. JOIN across databases, and every index immediately becomes decorative without a single error — how to prove it with EXPLAIN and build a mirror that converts tis620 to utf8mb4 during the dump, plus the sed trap that silently breaks tables.

#mariadb#mysql#charset#utf8mb4
10 min read·6 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
Migrating vBulletin 4.2.5 to Flarum: Lessons from 200,000 Posts
DirectAdmin

Migrating vBulletin 4.2.5 to Flarum: Lessons from 200,000 Posts

Migrating an old vBulletin 4.2.5 forum with over seven thousand members, over twenty thousand threads, and over two hundred thousand posts to Flarum — notes on pitfalls that cost real time, from guest userid 0 breaking FK constraints across an entire batch, nested md5 hashes for old passwords, and converting BBCode to s9e XML, to attachments stored on disk instead of in the DB and why I had to scp scripts instead of using heredoc

#flarum#vbulletin#migration#mariadb
11 min read·25 Jul
Recover MariaDB Redo Log Corruption with force_recovery and Reinit
Linux

Recover MariaDB Redo Log Corruption with force_recovery and Reinit

MariaDB would not start after an unclean shutdown — a corrupted InnoDB redo log took the mysql.global_priv system table down with it. This is the recovery sequence I actually used, starting with innodb_force_recovery to make the data readable, then dumping each db before reinitializing the whole system, with one rule never to raise force_recovery higher than necessary.

#mariadb#mysql#disaster-recovery#debugging
9 min read·25 Jul
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
Thai Data Migration Traps: VARCHAR, Idempotency, and OCR Vowels
Linux

Thai Data Migration Traps: VARCHAR, Idempotency, and OCR Vowels

Lessons from importing and migrating hundreds of thousands of Thai data rows — undersized VARCHAR columns silently truncating synthetic keys into collisions, idempotency requiring DELETE before INSERT to stop totals reaching 200%, collation treating su001 and SU001 as equal while storing both, and Thai vowels corrupted by OCR that need a normalization map before insert

#migration#mariadb#mysql#debugging
9 min read·24 Jul
Porting Excel Formulas to the Web: Floating-Point Traps
Linux

Porting Excel Formulas to the Web: Floating-Point Traps

Porting engineering formulas from an Excel file to a web calculator produced differences around 1e-13 — not a math bug, but differences in how JS and Excel evaluate floating-point powers and multiplication order, with a method for reading formulas and values separately using openpyxl and building fixtures that actually catch regressions.

#automation#python#debugging#structural
8 min read·23 Jul
Android Dev on MIUI/HyperOS — adb Traps on Windows
Linux

Android Dev on MIUI/HyperOS — adb Traps on Windows

adb is not broken, but Git Bash mangles /sdcard paths, PowerShell produces 0-byte screenshots, MIUI/HyperOS blocks the first installation, and here-strings swallow backslashes when generating PHP code — real traps I hit while developing an Android app on Windows, with commands that actually work

#android#windows#debugging#automation
8 min read·23 Jul
Inferring Cold Room Defrost Timing from Temperature Slopes
Linux

Inferring Cold Room Defrost Timing from Temperature Slopes

A cold room used to dehydrate glass noodles has no humidity sensors, but frost on the coil always flattens the temperature drop slope (dT/dt). This article uses the lumped-capacitance equation and time constant τ to detect frost and trigger demand defrost with working Python code, along with calculations for R404A COP and water removed per cycle.

#refrigeration#iot#monitoring#python
10 min read·22 Jul
Government ICT Computer Price Criteria + DIY Builds with Scripts
Linux

Government ICT Computer Price Criteria + DIY Builds with Scripts

The December 2568 government ICT reference price criteria clearly define specifications for 20,000 baht office computers and 24,000 baht processing computers. In this article, I read the actual criteria item by item, then write a Python script to pull Advice prices and put together DIY builds to compare how much better the value is than buying prebuilt machines.

#sysadmin#python#automation#hardware
9 min read·22 Jul
reCamera + Gimbal: RISC-V Cross-Compilation, CAN, and Node-RED
Linux

reCamera + Gimbal: RISC-V Cross-Compilation, CAN, and Node-RED

reCamera is an AI camera on a RISC-V chip mounted on two brushless axes, with rotation controlled over CAN bus at a resolution of 0.01 degrees. This article covers cross-compiling C for riscv64 musl, uploading to the device with scp, the CAN frame structure for motor control, reading back the 15-bit encoder, finding motor zero using current, a Node-RED dashboard + PID + auto-track, and STP files for 3D-printing the housing.

#recamera#iot#automation#python
10 min read·21 Jul
MDES 2564 Government CCTV Price Limits and a Hikvision PoE BOM
Network

MDES 2564 Government CCTV Price Limits and a Hikvision PoE BOM

Read the full MDES June 2564 government CCTV reference pricing and basic specifications before setting a budget, then design a Hikvision IP/PoE BOM that meets the minimum specifications, reference price ceilings, 30-day recording retention rule, and requirement to allow at least 3 brands to compete.

#cctv#hikvision#networking#monitoring
10 min read·21 Jul
Read a Toledo RS-232 Scale over Bluetooth with PowerShell
Linux

Read a Toledo RS-232 Scale over Bluetooth with PowerShell

Connect a TWT-01 digital scale with only an RS-232 port to a PC through a BT578 Bluetooth adapter, then read its weight in real time with PowerShell — from Bluetooth pairing and finding the COM port by MAC address to decoding 18-byte Toledo Continuous frames and the null-byte and scale auto-sleep pitfalls I encountered in practice.

#serial#windows#automation#iot
8 min read·20 Jul
Control TP-Link Omada OC200 via REST API with Python
Network

Control TP-Link Omada OC200 via REST API with Python

A practical guide to logging into an OC200 controller through REST API v2 with Python — handling CSRF tokens, self-signed certs, fetching sites/devices/SSIDs/DHCP/port-forward rules, and writing back with PATCH, including the read-only fields that cause a nonzero errorCode

#omada#networking#api#python
8 min read·20 Jul
Network-as-code on MikroTik RouterOS
Network

Network-as-code on MikroTik RouterOS

A network-as-code approach for MikroTik — save /export output as a file, strip secrets with a sanitize script before sharing, split it into sections, then generate configs for multiple sites from Jinja2 templates + one set of variables

#mikrotik#routeros#networking#automation
9 min read·19 Jul
Reading a DTSU666 3-Phase Meter with Raspberry Pi over Modbus RS485
Linux

Reading a DTSU666 3-Phase Meter with Raspberry Pi over Modbus RS485

Notes on connecting a DTSU666 Smart Power Sensor to a Raspberry Pi over RS485, reading 3-phase electrical measurements from multiple meters using Modbus RTU, decoding 32-bit floats correctly, and storing them in SQLite/MySQL before exporting through MQTT and a REST API, including a negative-value bug I ran into myself

#modbus#rs485#iot#dtsu666
11 min read·19 Jul
Screenshot Multiple Domains Directly from Origin, Bypassing Cloudflare
Network

Screenshot Multiple Domains Directly from Origin, Bypassing Cloudflare

Need screenshots of dozens of domains for inspection, or want to confirm that the origin server (not the CDN cache) renders correctly — but Chrome's screenshot flag has been broken since version 132, and AV reverts hosts edits? This article uses Playwright to override DNS at the process level, solving both problems.

#debugging#cloudflare#python#automation
7 min read·18 Jul
~30 Seconds Turns Tiny: Flarum's Litedown Subscript Trap
Linux

~30 Seconds Turns Tiny: Flarum's Litedown Subscript Trap

Write "~30 seconds" in a Flarum post and 30 turns into a tiny subscript — because Flarum's Litedown interprets ~ as a subscript opener. Thai users who use ~ to mean "approximately" run into this regularly. This article explains the cause, workarounds, and database fixes for content stored as s9e XML rather than raw markdown.

#flarum#markdown#debugging#php-fpm
6 min read·18 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 Stopped After Moving to Cloudflare — Proxied Mail Records
Network

Mail Stopped After Moving to Cloudflare — Proxied Mail Records

After adding a domain to Cloudflare and pointing DNS at the host, incoming mail suddenly stops — the most common cause I see is leaving mail/smtp/pop records proxied (orange cloud), even though Cloudflare's proxy only handles HTTP/S. This article covers which records must be grey + token/SSL pitfalls.

#cloudflare#dns#mail#security
7 min read·17 Jul
nginx heap overflow spans 15 years—version checks aren't enough
Security

nginx heap overflow spans 15 years—version checks aren't enough

CVE-2026-42533 affects nginx versions 0.9.6 through 1.31.2, spanning 15 years, but actual exposure depends on the config, not the version. The problem is that news reports describe narrower conditions than the real ones. Checking against those reports can return "safe" even when the config still meets the conditions.

#security#nginx#cve#vulnerability
9 min read·16 Jul
Writing Scripts on Windows for Linux — Two File Cleanup Traps
Linux

Writing Scripts on Windows for Linux — Two File Cleanup Traps

Writing helper scripts on Windows and using scp to run them on Linux is routine work, but two things keep catching me out — d:\ paths embedded in scripts turn into strange filenames in /tmp that trigger the file monitor, and token/payload files get left behind on the server. This article lays out my rules for avoiding these mistakes.

#automation#windows#linux#sysadmin
6 min read·16 Jul
Read-only Debian shared-host security audit — avoid banning yourself
Security

Read-only Debian shared-host security audit — avoid banning yourself

Audit the security of a Debian server running DirectAdmin in read-only mode first — but the first trap is that scan traffic itself triggers CSF's brute-force rules and gets your own IP banned. This article lays out a safe audit sequence + areas to check in 2024-2026

#security#hardening#csf#cve
9 min read·16 Jul
Reading Modbus RTU over an RS485 Gateway Without Phantom Values
Linux

Reading Modbus RTU over an RS485 Gateway Without Phantom Values

Connecting multiple Modbus RTU meters/sensors on an RS485 bus through a serial-to-Ethernet gateway can produce phantom values, incorrect readings, or devices that do not actually exist — because a transparent gateway uses RTU-over-TCP, which requires assembling frames and calculating CRC yourself, and validating every reply. This article covers the rules I learned from doing it.

#modbus#rs485#iot#python
9 min read·15 Jul
Create .ppk Files for plink/pscp on Windows Without Opening puttygen
Linux

Create .ppk Files for plink/pscp on Windows Without Opening puttygen

puttygen.exe on Windows is GUI-only and cannot batch-convert OpenSSH to .ppk (it returns unrecognised option) — this article writes PPK v3 files directly with Python, including the hard-to-find HMAC-SHA-256 MAC formula, ready to use with plink/pscp/WinSCP.

#ssh#putty#windows#python
7 min read·15 Jul
Generate PromptPay QR (EMVCo) in Pure Python — No External Libraries
Linux

Generate PromptPay QR (EMVCo) in Pure Python — No External Libraries

Want to generate PromptPay payment QR codes in your own POS/web system without calling a bank API? In this article, I build the EMVCo TLV string + CRC16 myself in pure Python, producing a payload that matches the Thai QR specification and can be scanned for payment by any banking app, along with the pitfalls that stop apps from reading it.

#python#promptpay#api#automation
8 min read·15 Jul
USB in WSL2 with usbipd-win — Real Hardware for Linux on Windows
Linux

USB in WSL2 with usbipd-win — Real Hardware for Linux on Windows

WSL2 cannot see USB devices because it is a VM without a USB controller — usbipd-win passes devices from Windows directly to the WSL kernel with 3 commands, list/bind/attach, plus lessons from actual use: attachments drop when unplugged, the CRLF trap, and USB modems taking over the default route

#usbip#wsl2#windows#linux
7 min read·11 Jul
libmodsecurity3 + nginx — only ctl:ruleEngine exclusions work
Security

libmodsecurity3 + nginx — only ctl:ruleEngine exclusions work

ModSecurity v3 (libmodsecurity3) + nginx + OWASP CRS — the ctl:ruleRemoveById taught in the guides does nothing and fails silently. This article covers what I found after trying every approach: ctl:ruleEngine works, scoped with a Host+URI chained rule, and the exclusion file must load before CRS.

#modsecurity#nginx#security#firewall
9 min read·10 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
LAN Access for a Team of 7 Without Open Ports: Cloudflare Zero Trust
Network

LAN Access for a Team of 7 Without Open Ports: Cloudflare Zero Trust

A team of 7 needs RDP access to machines on the LAN without opening any ports to the internet — the Cloudflare Zero Trust architecture (WARP + cloudflared), with 3 lessons from implementation: a forgotten IdP setup, Gateway defaults that allow everything, and the default-deny rule people forget most often

#cloudflare#zero-trust#vpn#remote-access
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
AdSense Says ads.txt Is Missing: Tracing the Logs Layer by Layer
Network

AdSense Says ads.txt Is Missing: Tracing the Logs Layer by Layer

The AdSense Sites page reports ads.txt as "Not found" even though the file exists and is correct — a forensic investigation using curl + access logs to prove, layer by layer, whether Googlebot visited and what it received. Case closed: nothing was blocking it; Google's own status was stale.

#adsense#nginx#cloudflare#logging
9 min read·8 Jul
Recovering Old Website Images with Wayback Machine CDX API + Python
Backup

Recovering Old Website Images with Wayback Machine CDX API + Python

A website over a decade old had broken images throughout because it hotlinked to a dead CDN — I wrote a Python script to list images from the Wayback Machine CDX API and restore them to their original paths without touching a single character of HTML, with the full script I actually used.

#wayback#python#backup#disaster-recovery
9 min read·7 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
Using Claude to Upgrade Proxmox 8 to 9 and Rebuild Windows VMs
Linux

Using Claude to Upgrade Proxmox 8 to 9 and Rebuild Windows VMs

A real case using VS Code + Claude to upgrade an entire Proxmox cluster from 8 to 9, then delete and rebuild all Windows VMs for VDI without ever SSHing into a host myself. I have laid out the commands and scripts Claude generated during the actual work as steps that a person or AI can read and run again.

#claude-code#ai#vscode#proxmox
13 min read·20 Jun
Edit Videos with Claude Using Thai Prompts, No Video Editor Needed
AI

Edit Videos with Claude Using Thai Prompts, No Video Editor Needed

How I actually use Claude in VS Code to trim, resize, join, and add background music to videos by typing in Thai, without memorizing ffmpeg commands or opening a video editor. Includes getting AI to compose music, NVIDIA GPU acceleration, and Mac and Linux instructions for people who have never used Claude.

#claude-code#ffmpeg#video-editing#vscode
11 min read·19 Jun
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
Put an Idle VPS to Work with WireGuard — A Complete Client Guide
Network

Put an Idle VPS to Work with WireGuard — A Complete Client Guide

Turn a VPS you signed up for on an annual plan into a WireGuard hub for accessing your home LAN anytime, without port forwarding — covering app installation, config imports, QR scanning, troubleshooting, and administration

#wireguard#vpn#vps#networking
12 min read·9 Jun
Claude Builds a Steel Shed in SketchUp, Then Runs FEA and a Heatmap
AI

Claude Builds a Steel Shed in SketchUp, Then Runs FEA and a Heatmap

In the final part of the series, I ask Claude to build an entire mono-slope steel shed in SketchUp, layer by layer from concrete columns to roof tiles, then analyze its strength with PyNite and apply a heatmap based on the actual forces.

#sketchup#fea#structural-analysis#steel-design
12 min read·5 Jun
Driving SketchUp with Claude Code, Part 2 — MCP Plugin Bug Fixes
AI

Driving SketchUp with Claude Code, Part 2 — MCP Plugin Bug Fixes

Let Claude Code actually "see" and "drive" SketchUp through a community MCP plugin, with fixes for 2 time-wasting bugs — a broken PyPI wheel and a UI freeze caused by a blocking socket

#mcp#claude-code#claude#sketchup
9 min read·5 Jun
Driving SketchUp with Claude Code, Part 1 — uv and PyNite Setup
AI

Driving SketchUp with Claude Code, Part 1 — uv and PyNite Setup

Start a series on using Claude Code to draw 3D steel structures in SketchUp and run FEA calculations. This first part covers setup only, configuring Claude permissions, installing uv, and creating a conda env with PyNite.

#claude-code#claude#ai#sketchup
9 min read·5 Jun
Auto-Unblock the Office in CSF with a Geo+Account Gate
Security

Auto-Unblock the Office in CSF with a Geo+Account Gate

A real case of a client office whose IP changes daily, with a ghost device using an old password that repeatedly gets the whole office blocked by CSF. How I automated unblocking with a narrow account+geo gate that lets the real office through while keeping foreign credential attacks blocked.

#csf#firewall#brute-force#geoip
12 min read·4 Jun
A Telegram Bot for DA Server Monitoring with a Small Blast Radius
Network

A Telegram Bot for DA Server Monitoring with a Small Blast Radius

A guide to setting up a Telegram bot as a lightweight control surface for monitoring a DirectAdmin server — read-only commands plus IP blocking/unblocking only, with no open ports, no added services, and a blast radius limited by least privilege at every layer

#telegram#bot#monitoring#alerting
13 min read·1 Jun
Off-Site Backups with Pull Architecture + rclone/rsync
Backup

Off-Site Backups with Pull Architecture + rclone/rsync

Add off-site Layer 3 to complete 3-2-1 with pull architecture (the destination host fetches the data), rclone + rsync, and lessons from real pitfalls involving NAT, RSA host keys, cwRsync, and PID recycling.

#backup#offsite#disaster-recovery#rclone
12 min read·28 May
Rebuilding DirectAdmin Backups with NFS and POSIX ACL in Production
Backup

Rebuilding DirectAdmin Backups with NFS and POSIX ACL in Production

A record of rebuilding backups on a DirectAdmin server after migrating to a new machine — from FTP push that broke at three layers to an NFSv4 hard mount + POSIX ACL, with kernel-level lessons learned along the way.

#backup#nfs#posix-acl#directadmin
13 min read·28 May
Reading exim mainlog for Stuck Clients — Mail Forensics Part 1
Security

Reading exim mainlog for Stuck Clients — Mail Forensics Part 1

How I read /var/log/exim/mainlog to distinguish an office machine using the wrong password from an attacker running a brute force attack, with the commands I use when customers need answers fast.

#mail-forensics#exim#mail#smtp
12 min read·23 May
Tracing Dovecot IMAP/POP Failures on DirectAdmin and Keeping 90-Day Logs
Security

Tracing Dovecot IMAP/POP Failures on DirectAdmin and Keeping 90-Day Logs

A follow-up to Mail Forensics — trace IMAP/POP failures in /var/log/mail.log on DirectAdmin, distinguish stuck clients from attackers using cross-protocol ratios, and adjust logrotate to keep a full 90 days of logs instead of defaults that lose them within days

#mail#dovecot#imap#pop3
11 min read·23 May
qcow2 or ZFS — Why I Switched After 12 Years on the Same Server
Linux

qcow2 or ZFS — Why I Switched After 12 Years on the Same Server

The reasons behind my storage choices for a Proxmox server that has run for 12 years without a reinstall — why I chose qcow2 in 2014, why I only moved to ZFS in 2026, and what actually changed the calculus.

#zfs#qcow2#proxmox#storage
12 min read·21 May
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
DirectAdmin from CentOS 7 to Debian 12 on Proxmox (Series Index)
DirectAdmin

DirectAdmin from CentOS 7 to Debian 12 on Proxmox (Series Index)

Notes on migrating a DirectAdmin shared host from CentOS 7 (EOL) to Debian 12 on Proxmox, serving 80+ customers, split into 5 parts with an overview of the process and links to every part

#migration#server-migration#directadmin#custombuild
8 min read·20 May
DA Migration Finale — Security Fixes and Hardening After Stabilizing
Security

DA Migration Finale — Security Fixes and Hardening After Stabilizing

Wrapping up the cross-distro DirectAdmin migration series with security work after the server stabilized — sudoers wildcard CVE, OpenSSL SECLEVEL, ModSec exclusions before CRS, a csfpost drop-in, and 5 layers that survive DA updates

#security#hardening#directadmin#modsecurity
12 min read·20 May
Moving DA from CentOS 7 to Debian 12, Part 4 — Cutover and 17 Issues
DirectAdmin

Moving DA from CentOS 7 to Debian 12, Part 4 — Cutover and 17 Issues

The actual cutover, where the near-0 downtime plan fell apart because of the DA Legacy license and slow qcow2 reads, ended with 1 hour of downtime and 17 issues in quick succession after the switch — critical web stack outages, medium issues affecting subsets of services, and minor debugging notes.

#cutover#migration#directadmin#qcow2
13 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
Moving DA to Debian 12, Part 2 — Switching Storage to a ZFS Mirror
Linux

Moving DA to Debian 12, Part 2 — Switching Storage to a ZFS Mirror

Replace the three storage layers of mdadm RAID1 + ext4 + qcow2 with a single layer of ZFS mirror + raw zvol while the old VM stays online, by degrading RAID to a single disk.

#zfs#raid#storage#snapshot
11 min read·20 May
DA CentOS 7 → Debian 12 on Proxmox Part 1 — NAT pre-stage
DirectAdmin

DA CentOS 7 → Debian 12 on Proxmox Part 1 — NAT pre-stage

Preparing a new VM on an internal bridge with NAT while the old VM continues serving customers, reducing downtime when migrating DirectAdmin from CentOS 7 to Debian 12 on Proxmox.

#nat#proxmox#kvm#migration
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
OpenClaw vs. VSCode + AI Agent: Which Should You Use?
AI

OpenClaw vs. VSCode + AI Agent: Which Should You Use?

Comparing two approaches that turn AI from a chatbot into an assistant that gets work done — a chat-app gateway like OpenClaw and an editor-based setup like VSCode + AI Agent, covering workflows, token costs, and security basics for beginners.

#ai#openclaw#vscode#claude-code
14 min read·19 Feb
Build a Desktop AI Server with WSL2 + Ollama + OpenClaw
AI

Build a Desktop AI Server with WSL2 + Ollama + OpenClaw

A record of building a home AI server from scratch, starting with Windows 11 IoT, installing WSL2 + Ubuntu, setting up Ollama to run LLMs on two GPUs, then adding multiple OpenClaw instances through systemd, covering drivers, custom Modelfiles, user isolation, and benchmarks

#wsl2#ollama#openclaw#local-llm
18 min read·18 Feb