The restored rig's RunicNPC says it is already managed, so a fresh site adopts none of its profiles and its first push empties them; chat styles are never adopted either. They come from the fixture now, through Module-Rust's onDemoSeed (needs the release carrying DM26; an older module ignores these keys): - npcs.factions: bandits and guards, allied; - npcs.profiles: bandit (roamer, rnpc_raider) and guard (sentry, heavy, rnpc_campguard, heals), both on the demo server. Only the fields that differ from RunicNPC's defaults are listed; - chat: [VIP] in gold and [MOD] in green. The baseline's placements (bandit-1, bandit-2, guard-1) spawn again once the site pushes these. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
deploy/demo — demo.runicgateway.com
The public demo site: the normal image with DEMO_MODE=true, wiped every two hours together
with its Rust server. Design of record: docs/website/DEMO_MODE.md.
| File | What it is |
|---|---|
docker-compose.yml |
The app and its database. No bot and no ntfy: the demo sends nothing outward (§5) |
.env.example |
Every variable the host's .env needs, with what each one is for |
seed.json |
The fixture seed:demo writes after every wipe: the four logins, settings, content, and the Rust module's server link and Steam link (§7.3). Passwords and credentials are "$env:NAME" references to .env |
rig.mjs |
Versions (plan), the rig restore (restore), the baseline capture (baseline) and the smoke check (smoke), against the Pterodactyl client API (§7.2, §7.5) |
Two workflows drive it, both on the demo-site runner:
demo-wipe.yml: every 2 hours on the hour (UTC), on a push tomainthat changes this directory, and by hand. Versions, then the rig, then the site, then a smoke check.demo-baseline.yml: by hand only. It captures the rig's current state asdemo-baseline.tar.gz, which every wipe restores.
One-time host setup
- The
demo-siterunner in host mode on the demo host, with Docker and Compose, andnodeon thePATH(foractions/checkout). The host must reachgitea.whitlocktech.com, the Pterodactyl panel and the rig's sidecar port. sudo mkdir -p /opt/demo.runicgateway.com, owned by the runner's user (or the runner runs as root). To use another path, set theDEMO_DIRActions variable.- Copy
.env.exampleto/opt/demo.runicgateway.com/.envand fill every blank. Generate secrets on the host, e.g.openssl rand -hex 32. The file never leaves the host. - Log the host in to the registry if the images are not public:
docker login gitea.whitlocktech.com. - Point the external reverse proxy at
<host>:DEMO_HOST_PORT(default 3000). - Run Demo wipe by hand. The first run finds no baseline, so it leaves the rig as it is and starts it.
Then set the demo default set up through the site: the permission groups, a few NPCs, a clan. Run Demo baseline while nobody else is changing anything. Every later wipe returns the rig to that.
The panel URL and the rig's server identifier default to http://192.168.0.12 and 6eb9d621
(rust-oxide). Override them with the PTERODACTYL_URL and PTERODACTYL_SERVER Actions
variables. PTERODACTYL_CLIENT_KEY is the demo subuser's key, an Actions secret.
What the wipe keeps on the host
state/ in the deploy directory:
bundle.json: the Rust bundle last written onto the rig. A new bundle is written only when this differs.modules.env:MODULES=rust@<version>=<manifest>, the newest Module-Rust release on the bundle's protocol. When no release matches a new bundle yet, the wipe keeps this file and the rig's bundle as they were and warns (§7.5).plan.json: this cycle's decision, fromplantorestore.
modules/ keeps the unpacked module between wipes. down -v drops the database and the uploads,
never this directory.