Domain Isolation

Give Each Domain Its Own Directory ยท Stop the Flat File Chaos
Plan Document ยท Walter ๐Ÿฆ‰ ยท March 17, 2026
DRAFT

I. The Problem

Right now, every domain serves from the same flat directory: /mnt/public/.

This means 1.foo/deck, 3.foo/deck, flawless.engineering/deck, and 1234567.foo/deck all serve the exact same file. There are ~170 files in /mnt/public/ โ€” all of them accessible from every domain. There's no separation. No isolation. No identity per domain.

The only exception is drip.xxx, which already has its own root at /mnt/public/drip-xxx-site/.

II. The Idea

Each domain gets its own subfolder in /mnt/public/, named after the domain itself:

/mnt/public/
โ”œโ”€โ”€ 0.foo/           โ† serves 0.foo
โ”œโ”€โ”€ 1.foo/           โ† serves 1.foo
โ”œโ”€โ”€ 2.foo/           โ† serves 2.foo
โ”œโ”€โ”€ 3.foo/           โ† serves 3.foo
โ”‚   ...
โ”œโ”€โ”€ 9.foo/           โ† serves 9.foo
โ”œโ”€โ”€ 123.foo/         โ† serves 123.foo
โ”œโ”€โ”€ 1234567.foo/     โ† serves 1234567.foo
โ”œโ”€โ”€ clankers.discount/
โ”œโ”€โ”€ flawless.engineering/
โ”œโ”€โ”€ drip.xxx/        โ† already exists (drip-xxx-site โ†’ renamed)
โ”œโ”€โ”€ patty.adult/
โ”œโ”€โ”€ vilka.lol/       โ† note: vilka.lol serves from Matilda, not vault
โ””โ”€โ”€ (old flat files remain untouched for now)

Step 1: Change the nginx roots. Don't move any files. Just point each domain's root to its subfolder. Create the empty subfolders. Everything breaks (404s everywhere). That's expected โ€” it tells us exactly which domain was serving which files.

Step 2: See what breaks. The domain monitor at 0.foo will immediately show which domains go from 200 to 404. The ones that break are the ones that had content. The ones that stay 403 were already empty.

Step 3: Move files to their new homes. This is the part that requires decisions โ€” which files belong to which domain. That's a separate step, done file-by-file with Daniel's input.

III. Current State โ€” Who Has What

Domains with actual content (served from /mnt/public/):

Domains with NO content (empty single-digit .foo + counting sequence):

IV. Execution Plan

STEP 1 โ€” CREATE SUBFOLDERS

Create a subfolder for every active domain:

mkdir -p /mnt/public/{0,1,2,3,4,5,6,7,8,9}.foo
mkdir -p /mnt/public/{123,1234,12345,123456,1234567,12345678,123456789}.foo
mkdir -p /mnt/public/clankers.discount
mkdir -p /mnt/public/flawless.engineering
mkdir -p /mnt/public/drip.xxx
mkdir -p /mnt/public/patty.adult
mkdir -p /mnt/public/if-anyone-builds-it-everyone-dies.{help,rip}

Just creates empty directories. Changes nothing.

STEP 2 โ€” UPDATE NGINX ROOTS

Change every domain's root directive from /mnt/public to /mnt/public/{domain}.

Example: 1.foo goes from root /mnt/public; to root /mnt/public/1.foo;

This is a sed operation on domains.conf โ€” or more safely, a rewrite of the file from a template.

Backup first: cp domains.conf domains.conf.bak-pre-isolation

STOP โ€” REVIEW NGINX DIFF

Why: This changes the serving root for every domain simultaneously. If the nginx config is wrong, everything goes down.

What happens: Show the diff of the new config vs the old one. Daniel reviews.

How to continue: Daniel says "looks right, reload."

STEP 3 โ€” RELOAD NGINX

nginx -t && systemctl reload nginx

At this point, most domains return 403 (empty folder, no index). 1.foo returns 404 for everything because its files are still in the parent directory. This is expected and correct โ€” it's the diagnostic step.

STEP 4 โ€” MOVE THE KNOWN FILES

Move files that clearly belong to specific domains:

# 0.foo โ€” the domain monitor
mv domain-status.html 0.foo/

# 123.foo โ€” family front door
mv 123.foo.html 123.foo/index.html

# 12345.foo โ€” Charlie's thing
mv 12345.foo.html 12345.foo/index.html

# clankers.discount โ€” fleet dashboard  
mv clankers.html clankers.discount/index.html
mv clankers-backups/ clankers.discount/clankers-backups/

# flawless.engineering โ€” case studies
mv flawless-engineering.html flawless.engineering/index.html
mv flawless.html flawless.engineering/  (if different)

# patty.adult
mv patty-adult*.html patty.adult/
(rename main one to index.html)

# if-anyone-builds-it-everyone-dies.*
mv dies-help.html if-anyone-builds-it-everyone-dies.help/index.html
mv dies-rip.html if-anyone-builds-it-everyone-dies.rip/index.html

# drip.xxx โ€” already has its folder, just rename
mv drip-xxx-site drip.xxx  (or symlink)
DECISION โ€” WHAT GOES TO 1.FOO?

Everything else โ€” the entire document library โ€” goes to /mnt/public/1.foo/. This is the main vault. All format specs, plans, reports, decks, fucks, PDFs, text files. 1.foo is the system domain.

The question is: do we move the files, or symlink them? Moving is cleaner. Symlinking preserves the old paths as a safety net.

STOP โ€” VERIFY EACH DOMAIN

Why: After moving files, every domain needs to be checked. The monitor at 0.foo will show the status, but we should also spot-check key URLs manually.

What to verify:

How to continue: All key URLs verified working.

STEP 5 โ€” UPDATE SCRIPTS

Scripts that write to /mnt/public/ need to be updated to write to the correct subfolder:

V. What This Enables

VI. Risks

RISK โ€” BROKEN LINKS

Every external link to 1.foo/something will break if something.html isn't in /mnt/public/1.foo/. This includes links shared in group chat, in documents, in MEMORY.md, etc. Mitigation: move all document files to 1.foo/ before reloading nginx. Or: keep the flat directory as a fallback with try_files.

RISK โ€” UPLOAD SCRIPT

The upload endpoint at 1.foo/upload writes to /mnt/public/. After isolation, uploads would go to /mnt/public/1.foo/. Need to update the upload script's target directory.

RISK โ€” CLANKERS BACKUPS

The fleet monitor writes backups to /mnt/public/clankers-backups/. Links in the dashboard point there. Need to update both the monitor script and the backup path to live inside clankers.discount/.