vivivi.games

← Dev log | 日本語版

Working with Xserver — FTP, .htaccess, and deploys that fail

Article three. The server is Xserver, for the deeply unglamorous reason that I already had an account. Getting GitHub to publish to it automatically, though, turned up a few things worth knowing.

The setup

When something is merged into main, GitHub Actions minifies the HTML, sends it to Xserver over FTP, and checks that the version string on the other end matches. All I do is say "merge it".

There are three destinations: the game itself, its preview environment, and the portal site. The game and its preview share one FTP account and differ only by folder; the portal is a separate domain, so it has its own account.

Things that caught me out, in no particular order

FTP just fails sometimes

This is the most common one. Roughly one deploy in a few fails with an FTP timeout. I've never found the cause, but re-running the failed job almost always fixes it. I used to investigate each time; now I treat it as transient and have the AI re-run the failed job when it happens. Three failures in a row means something is genuinely broken — that's the threshold.

A subdomain is a folder

Create a subdomain on Xserver and it makes a folder of that name inside the parent domain's public directory, then serves it as the document root. Which means game.example.com/ and www.example.com/game/ point at the same place. Not knowing that, I was confused for a while about why the same game appeared at two URLs.

FTP accounts can be scoped to that folder, so separating them for the game and the portal means work on one can't break the other.

A preview environment is essential

Pushing an AI's changes straight to production is frightening. So opening a PR now publishes to a preview URL automatically, and I check there before merging. The preview carries noindex so it never shows up in search.

I got this wrong once: the AI pushed a portal update straight to production, skipping the preview. It had assumed "the portal has no preview environment" and carried on, when in fact a preview workflow existed. A look at the repository would have shown that. I also said "just put it up", so I didn't stop it either. This is what happens when assumption arrives before verification — for AIs and for humans.

.htaccess is resolved per directory

I put a "redirect non-www to www" rule at the portal root, and it had no effect inside the game folder. When each folder has its own .htaccess, the deeper one wins. The same rule had to be added on the game side too.

You can't verify minified output with string matching

The HTML that reaches production is minified, so checking "does this variable name exist" fails. Verify by function name or structure instead, or embed a version string somewhere dedicated and check only that. The verification method has to be designed around minification from the start.

How it works today

TaskOwner
Code changes and PRsAI
Preview reviewMe
Merge instructionMe
Merge and production deployAI (after my go-ahead)
Re-running failed deploysAI
FTP accounts, DNS, domain settingsMe (server control panel)

What I wish I'd known

Series: "I wish I'd known this from the start"

← Back to the dev log